diff options
Diffstat (limited to 'java/com/android/incallui/rtt')
20 files changed, 1175 insertions, 0 deletions
diff --git a/java/com/android/incallui/rtt/impl/AndroidManifest.xml b/java/com/android/incallui/rtt/impl/AndroidManifest.xml new file mode 100644 index 000000000..fc0705d7e --- /dev/null +++ b/java/com/android/incallui/rtt/impl/AndroidManifest.xml @@ -0,0 +1,26 @@ +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<manifest + package="com.android.incallui.rtt.impl" + xmlns:android="http://schemas.android.com/apk/res/android"> + <application android:theme="@style/Theme.AppCompat"> + <activity + android:name=".RttChatActivity" + android:exported="false" + android:theme="@style/DialerThemeBase.NoActionBar" + android:windowSoftInputMode="adjustResize"/> + </application> +</manifest> diff --git a/java/com/android/incallui/rtt/impl/RttChatActivity.java b/java/com/android/incallui/rtt/impl/RttChatActivity.java new file mode 100644 index 000000000..96056f746 --- /dev/null +++ b/java/com/android/incallui/rtt/impl/RttChatActivity.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.incallui.rtt.impl; + +import android.os.Bundle; +import android.os.SystemClock; +import android.support.annotation.Nullable; +import android.support.v4.app.FragmentActivity; +import android.view.View; + +/** Activity to for RTT chat window. */ +public class RttChatActivity extends FragmentActivity { + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_rtt); + getSupportFragmentManager() + .beginTransaction() + .add( + R.id.fragment_rtt, + RttChatFragment.newInstance("", "Jane Williamson", SystemClock.elapsedRealtime())) + .commit(); + getWindow().setStatusBarColor(getColor(R.color.rtt_status_bar_color)); + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + } +} diff --git a/java/com/android/incallui/rtt/impl/RttChatAdapter.java b/java/com/android/incallui/rtt/impl/RttChatAdapter.java new file mode 100644 index 000000000..1db4c6bad --- /dev/null +++ b/java/com/android/incallui/rtt/impl/RttChatAdapter.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.incallui.rtt.impl; + +import android.content.Context; +import android.support.annotation.MainThread; +import android.support.v7.widget.RecyclerView; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import com.android.dialer.common.Assert; +import com.android.dialer.common.LogUtil; +import com.android.dialer.common.concurrent.ThreadUtil; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +/** Adapter class for holding RTT chat data. */ +public class RttChatAdapter extends RecyclerView.Adapter<RttChatMessageViewHolder> { + + interface MessageListener { + void newMessageAdded(); + } + + private final Context context; + private final List<RttChatMessage> rttMessages = new ArrayList<>(); + private int lastIndexOfLocalMessage = -1; + private int lastIndexOfRemoteMessage = -1; + private final TypeBot typeBot; + private final MessageListener messageListener; + + RttChatAdapter(Context context, MessageListener listener) { + this.context = context; + this.messageListener = listener; + typeBot = new TypeBot(text -> ThreadUtil.postOnUiThread(() -> addRemoteMessage(text))); + } + + @Override + public RttChatMessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + LayoutInflater layoutInflater = LayoutInflater.from(context); + View view = layoutInflater.inflate(R.layout.rtt_chat_list_item, parent, false); + return new RttChatMessageViewHolder(view); + } + + @Override + public int getItemViewType(int position) { + return super.getItemViewType(position); + } + + @Override + public void onBindViewHolder(RttChatMessageViewHolder rttChatMessageViewHolder, int i) { + boolean isSameGroup = false; + if (i > 0) { + isSameGroup = rttMessages.get(i).isRemote == rttMessages.get(i - 1).isRemote; + } + rttChatMessageViewHolder.setMessage(rttMessages.get(i), isSameGroup); + } + + @Override + public int getItemCount() { + return rttMessages.size(); + } + + private void updateCurrentRemoteMessage(String newText) { + RttChatMessage rttChatMessage = null; + if (lastIndexOfRemoteMessage >= 0) { + rttChatMessage = rttMessages.get(lastIndexOfRemoteMessage); + } + RttChatMessage[] newMessages = RttChatMessage.getRemoteRttChatMessage(rttChatMessage, newText); + + if (rttChatMessage == null) { + lastIndexOfRemoteMessage = rttMessages.size(); + rttMessages.add(lastIndexOfRemoteMessage, newMessages[0]); + rttMessages.addAll(Arrays.asList(newMessages).subList(1, newMessages.length)); + notifyItemRangeInserted(lastIndexOfRemoteMessage, newMessages.length); + lastIndexOfRemoteMessage = rttMessages.size() - 1; + } else { + rttMessages.set(lastIndexOfRemoteMessage, newMessages[0]); + int lastIndex = rttMessages.size(); + rttMessages.addAll(Arrays.asList(newMessages).subList(1, newMessages.length)); + + notifyItemChanged(lastIndexOfRemoteMessage); + notifyItemRangeInserted(lastIndex, newMessages.length); + } + if (rttMessages.get(lastIndexOfRemoteMessage).isFinished()) { + lastIndexOfRemoteMessage = -1; + } + } + + private void updateCurrentLocalMessage(String newMessage) { + RttChatMessage rttChatMessage = null; + if (lastIndexOfLocalMessage >= 0) { + rttChatMessage = rttMessages.get(lastIndexOfLocalMessage); + } + if (rttChatMessage == null || rttChatMessage.isFinished()) { + rttChatMessage = new RttChatMessage(); + rttChatMessage.append(newMessage); + rttMessages.add(rttChatMessage); + lastIndexOfLocalMessage = rttMessages.size() - 1; + notifyItemInserted(lastIndexOfLocalMessage); + } else { + rttChatMessage.append(newMessage); + notifyItemChanged(lastIndexOfLocalMessage); + } + } + + void addLocalMessage(String message) { + LogUtil.enterBlock("RttChatAdapater.addLocalMessage"); + updateCurrentLocalMessage(message); + if (messageListener != null) { + messageListener.newMessageAdded(); + } + } + + void submitLocalMessage() { + LogUtil.enterBlock("RttChatAdapater.submitLocalMessage"); + rttMessages.get(lastIndexOfLocalMessage).finish(); + notifyItemChanged(lastIndexOfLocalMessage); + lastIndexOfLocalMessage = -1; + startChatBot(); + } + + void addRemoteMessage(String message) { + LogUtil.enterBlock("RttChatAdapater.addRemoteMessage"); + if (TextUtils.isEmpty(message)) { + return; + } + updateCurrentRemoteMessage(message); + if (messageListener != null) { + messageListener.newMessageAdded(); + } + } + + private void startChatBot() { + typeBot.scheduleMessage(); + } + + // TODO(wangqi): Move this out of this class once a bug is fixed. + private static class TypeBot { + interface Callback { + void type(String text); + } + + private static final String[] CANDIDATE_MESSAGES = + new String[] { + "To RTT or not to RTT, that is the question...", + "Making TTY great again!", + "I would be more comfortable with real \"Thyme\" chatting." + + " I don't know how to end this pun", + "お疲れ様でした", + "The FCC has mandated that I respond... I will do so begrudgingly", + "😂😂😂💯" + }; + private final Random random = new Random(); + private final Callback callback; + private final List<String> messageQueue = new ArrayList<>(); + private int currentTypingPosition = -1; + private String currentTypingMessage = null; + + TypeBot(Callback callback) { + this.callback = callback; + } + + @MainThread + public void scheduleMessage() { + Assert.isMainThread(); + if (random.nextDouble() < 0.5) { + return; + } + + String text = CANDIDATE_MESSAGES[random.nextInt(CANDIDATE_MESSAGES.length)]; + messageQueue.add(text); + typeMessage(); + } + + @MainThread + private void typeMessage() { + Assert.isMainThread(); + if (currentTypingPosition < 0 || currentTypingMessage == null) { + if (messageQueue.size() <= 0) { + return; + } + currentTypingMessage = messageQueue.remove(0); + currentTypingPosition = 0; + } + if (currentTypingPosition < currentTypingMessage.length()) { + int size = random.nextInt(currentTypingMessage.length() - currentTypingPosition + 1); + callback.type( + currentTypingMessage.substring(currentTypingPosition, currentTypingPosition + size)); + currentTypingPosition = currentTypingPosition + size; + // Wait up to 2s between typing. + ThreadUtil.postDelayedOnUiThread(this::typeMessage, 200 * random.nextInt(10)); + } else { + callback.type(RttChatMessage.BUBBLE_BREAKER); + currentTypingPosition = -1; + currentTypingMessage = null; + // Wait 1-11s between two messages. + ThreadUtil.postDelayedOnUiThread(this::typeMessage, 1000 * (1 + random.nextInt(10))); + } + } + } +} diff --git a/java/com/android/incallui/rtt/impl/RttChatFragment.java b/java/com/android/incallui/rtt/impl/RttChatFragment.java new file mode 100644 index 000000000..0b0ad2a8e --- /dev/null +++ b/java/com/android/incallui/rtt/impl/RttChatFragment.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.incallui.rtt.impl; + +import android.os.Bundle; +import android.os.SystemClock; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.OnScrollListener; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; +import android.widget.Chronometer; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.TextView; +import android.widget.TextView.OnEditorActionListener; +import com.android.incallui.rtt.impl.RttChatAdapter.MessageListener; + +/** RTT chat fragment to show chat bubbles. */ +public class RttChatFragment extends Fragment + implements OnClickListener, OnEditorActionListener, TextWatcher, MessageListener { + + private static final String ARG_CALL_ID = "call_id"; + private static final String ARG_NAME_OR_NUMBER = "name_or_number"; + private static final String ARG_SESSION_START_TIME = "session_start_time"; + + private RecyclerView recyclerView; + private RttChatAdapter adapter; + private EditText editText; + private ImageButton submitButton; + private boolean isClearingInput; + + private final OnScrollListener onScrollListener = + new OnScrollListener() { + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + if (dy < 0) { + hideKeyboard(); + } + } + }; + + /** + * Create a new instance of RttChatFragment. + * + * @param callId call id of the RTT call. + * @param nameOrNumber name or number of the caller to be displayed + * @param sessionStartTimeMillis start time of RTT session in terms of {@link + * SystemClock#elapsedRealtime}. + * @return new RttChatFragment + */ + public static RttChatFragment newInstance( + String callId, String nameOrNumber, long sessionStartTimeMillis) { + Bundle bundle = new Bundle(); + bundle.putString(ARG_CALL_ID, callId); + bundle.putString(ARG_NAME_OR_NUMBER, nameOrNumber); + bundle.putLong(ARG_SESSION_START_TIME, sessionStartTimeMillis); + RttChatFragment instance = new RttChatFragment(); + instance.setArguments(bundle); + return instance; + } + + @Nullable + @Override + public View onCreateView( + LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.frag_rtt_chat, container, false); + editText = view.findViewById(R.id.rtt_chat_input); + editText.setOnEditorActionListener(this); + editText.addTextChangedListener(this); + recyclerView = view.findViewById(R.id.rtt_recycler_view); + LinearLayoutManager layoutManager = new LinearLayoutManager(getContext()); + layoutManager.setStackFromEnd(true); + recyclerView.setLayoutManager(layoutManager); + recyclerView.setHasFixedSize(false); + adapter = new RttChatAdapter(getContext(), this); + recyclerView.setAdapter(adapter); + recyclerView.addOnScrollListener(onScrollListener); + submitButton = view.findViewById(R.id.rtt_chat_submit_button); + submitButton.setOnClickListener(this); + submitButton.setEnabled(false); + + String nameOrNumber = null; + Bundle bundle = getArguments(); + if (bundle != null) { + nameOrNumber = bundle.getString(ARG_NAME_OR_NUMBER, getString(R.string.unknown)); + } + TextView nameTextView = view.findViewById(R.id.rtt_name_or_number); + nameTextView.setText(nameOrNumber); + + long sessionStartTime = SystemClock.elapsedRealtime(); + if (bundle != null) { + sessionStartTime = bundle.getLong(ARG_SESSION_START_TIME, sessionStartTime); + } + Chronometer chronometer = view.findViewById(R.id.rtt_timer); + chronometer.setBase(sessionStartTime); + chronometer.start(); + return view; + } + + @Override + public void onClick(View v) { + if (v.getId() == R.id.rtt_chat_submit_button) { + adapter.submitLocalMessage(); + isClearingInput = true; + editText.setText(""); + isClearingInput = false; + } + } + + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + submitButton.performClick(); + return true; + } + return false; + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (isClearingInput) { + return; + } + adapter.addLocalMessage(RttChatMessage.getChangedString(s, start, before, count)); + } + + @Override + public void afterTextChanged(Editable s) { + if (TextUtils.isEmpty(s)) { + submitButton.setEnabled(false); + } else { + submitButton.setEnabled(true); + } + } + + @Override + public void newMessageAdded() { + recyclerView.smoothScrollToPosition(adapter.getItemCount()); + } + + private void hideKeyboard() { + InputMethodManager inputMethodManager = getContext().getSystemService(InputMethodManager.class); + if (inputMethodManager.isAcceptingText()) { + inputMethodManager.hideSoftInputFromWindow( + getActivity().getCurrentFocus().getWindowToken(), 0); + } + } +} diff --git a/java/com/android/incallui/rtt/impl/RttChatMessage.java b/java/com/android/incallui/rtt/impl/RttChatMessage.java new file mode 100644 index 000000000..85b045183 --- /dev/null +++ b/java/com/android/incallui/rtt/impl/RttChatMessage.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.incallui.rtt.impl; + +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.text.TextWatcher; +import com.google.common.base.Splitter; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** Message class that holds one RTT chat content. */ +final class RttChatMessage { + + static final String BUBBLE_BREAKER = "\n\n"; + private static final Splitter SPLITTER = Splitter.on(BUBBLE_BREAKER); + + boolean isRemote; + public boolean hasAvatar; + private final StringBuilder content = new StringBuilder(); + private boolean isFinished; + + public boolean isFinished() { + return isFinished; + } + + public void finish() { + isFinished = true; + } + + public void append(String text) { + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + if (c != '\b') { + content.append(c); + } else if (content.length() > 0) { + content.deleteCharAt(content.length() - 1); + } + } + } + + public String getContent() { + return content.toString(); + } + + /** + * Generates delta change to a text. + * + * <p>This is used to track text change of input. See more details in {@link + * TextWatcher#onTextChanged} + * + * <p>e.g. "hello world" -> "hello" : "\b\b\b\b\b\b" + * + * <p>"hello world" -> "hello mom!" : "\b\b\b\b\bmom!" + * + * <p>"hello world" -> "hello d" : "\b\b\b\b\bd" + * + * <p>"hello world" -> "hello new world" : "\b\b\b\b\bnew world" + */ + static String getChangedString(CharSequence s, int start, int before, int count) { + StringBuilder modify = new StringBuilder(); + if (before > count) { + int deleteStart = start + count; + int deleted = before - count; + int numberUnModifiedCharsAfterDeleted = s.length() - start - count; + char c = '\b'; + for (int i = 0; i < deleted + numberUnModifiedCharsAfterDeleted; i++) { + modify.append(c); + } + modify.append(s, deleteStart, s.length()); + } else { + int insertStart = start + before; + int numberUnModifiedCharsAfterInserted = s.length() - start - count; + char c = '\b'; + for (int i = 0; i < numberUnModifiedCharsAfterInserted; i++) { + modify.append(c); + } + modify.append(s, insertStart, s.length()); + } + return modify.toString(); + } + + /** Convert remote input text into an array of {@code RttChatMessage}. */ + static RttChatMessage[] getRemoteRttChatMessage( + @Nullable RttChatMessage currentMessage, @NonNull String text) { + Iterator<String> splitText = SPLITTER.split(text).iterator(); + List<RttChatMessage> messageList = new ArrayList<>(); + + String firstMessageContent = splitText.next(); + RttChatMessage firstMessage = currentMessage; + if (firstMessage == null) { + firstMessage = new RttChatMessage(); + firstMessage.isRemote = true; + } + firstMessage.append(firstMessageContent); + if (splitText.hasNext() || text.endsWith(BUBBLE_BREAKER)) { + firstMessage.finish(); + } + messageList.add(firstMessage); + + while (splitText.hasNext()) { + String singleMessageContent = splitText.next(); + if (singleMessageContent.isEmpty()) { + continue; + } + RttChatMessage message = new RttChatMessage(); + message.append(singleMessageContent); + message.isRemote = true; + if (splitText.hasNext()) { + message.finish(); + } + messageList.add(message); + } + + return messageList.toArray(new RttChatMessage[0]); + } +} diff --git a/java/com/android/incallui/rtt/impl/RttChatMessageViewHolder.java b/java/com/android/incallui/rtt/impl/RttChatMessageViewHolder.java new file mode 100644 index 000000000..c88786aa4 --- /dev/null +++ b/java/com/android/incallui/rtt/impl/RttChatMessageViewHolder.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.incallui.rtt.impl; + +import android.content.res.Resources; +import android.support.v7.widget.RecyclerView.ViewHolder; +import android.view.Gravity; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.LinearLayout.LayoutParams; +import android.widget.TextView; + +/** ViewHolder class for RTT chat message bubble. */ +public class RttChatMessageViewHolder extends ViewHolder { + + private final TextView messageTextView; + private final Resources resources; + private final ImageView avatarImageView; + private final View container; + + RttChatMessageViewHolder(View view) { + super(view); + container = view.findViewById(R.id.rtt_chat_message_container); + messageTextView = view.findViewById(R.id.rtt_chat_message); + avatarImageView = view.findViewById(R.id.rtt_chat_avatar); + resources = view.getResources(); + } + + void setMessage(RttChatMessage message, boolean isSameGroup) { + messageTextView.setText(message.getContent()); + LinearLayout.LayoutParams params = (LayoutParams) container.getLayoutParams(); + params.gravity = message.isRemote ? Gravity.START : Gravity.END; + params.topMargin = + isSameGroup + ? resources.getDimensionPixelSize(R.dimen.rtt_same_group_message_margin_top) + : resources.getDimensionPixelSize(R.dimen.rtt_message_margin_top); + container.setLayoutParams(params); + messageTextView.setEnabled(message.isRemote); + if (message.isRemote) { + if (isSameGroup) { + avatarImageView.setVisibility(View.INVISIBLE); + } else { + avatarImageView.setVisibility(View.VISIBLE); + avatarImageView.setImageResource(R.drawable.product_logo_avatar_anonymous_white_color_120); + } + } else { + avatarImageView.setVisibility(View.GONE); + } + } +} diff --git a/java/com/android/incallui/rtt/impl/res/color/message_bubble_color.xml b/java/com/android/incallui/rtt/impl/res/color/message_bubble_color.xml new file mode 100644 index 000000000..b3729ee20 --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/color/message_bubble_color.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" + android:color="#E0E0E0" /> + <item android:color="@android:color/white" /> +</selector>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/color/submit_button_background_color.xml b/java/com/android/incallui/rtt/impl/res/color/submit_button_background_color.xml new file mode 100644 index 000000000..0da2c374a --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/color/submit_button_background_color.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" + android:color="#BDBDBD" /> + <item android:color="#FFFFFF" /> +</selector>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/color/submit_button_color.xml b/java/com/android/incallui/rtt/impl/res/color/submit_button_color.xml new file mode 100644 index 000000000..2fe748f77 --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/color/submit_button_color.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" + android:color="#EEEEEE" /> + <item android:color="#2A56C6" /> +</selector>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/drawable/input_bubble_background.xml b/java/com/android/incallui/rtt/impl/res/drawable/input_bubble_background.xml new file mode 100644 index 000000000..ae372332e --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/drawable/input_bubble_background.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/pill_stroke"> + <shape android:shape="rectangle"> + <padding + android:bottom="0dp" + android:left="1dp" + android:right="1dp" + android:top="0dp"/> + <solid android:color="@android:color/transparent"/> + <corners android:radius="24dp"/> + </shape> + </item> + <item> + <shape android:shape="rectangle"> + <padding + android:bottom="1dp" + android:left="1dp" + android:right="1dp" + android:top="1dp"/> + <solid android:color="#102C3558"/> + <corners android:radius="24dp"/> + </shape> + </item> + <item> + <shape android:shape="rectangle"> + <padding + android:bottom="1dp" + android:left="1dp" + android:right="1dp" + android:top="0dp"/> + <solid android:color="#202C3558"/> + <corners android:radius="24dp"/> + </shape> + </item> + <item> + <shape android:shape="rectangle"> + <padding + android:bottom="1dp" + android:left="1dp" + android:right="1dp" + android:top="1dp"/> + <solid android:color="#382C3558"/> + <corners android:radius="24dp"/> + </shape> + </item> + <item> + <shape android:shape="rectangle"> + <padding + android:bottom="1dp" + android:left="0dp" + android:right="0dp" + android:top="0dp"/> + <solid android:color="#582C3558"/> + <corners android:radius="24dp"/> + </shape> + </item> + <item android:drawable="@drawable/pill_background"/> +</layer-list>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/drawable/message_bubble.xml b/java/com/android/incallui/rtt/impl/res/drawable/message_bubble.xml new file mode 100644 index 000000000..2b01f62f9 --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/drawable/message_bubble.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="@android:color/white"/> + <corners android:radius="20dp"/> +</shape>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/drawable/pill_background.xml b/java/com/android/incallui/rtt/impl/res/drawable/pill_background.xml new file mode 100644 index 000000000..cfad8df57 --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/drawable/pill_background.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <!-- Color is theme dependent and will be overridden in code. --> + <solid android:color="@android:color/white"/> + <corners android:radius="24dp"/> +</shape>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml b/java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml new file mode 100644 index 000000000..b48e8d43f --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/layout/activity_rtt.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <FrameLayout + android:id="@+id/fragment_rtt" + android:layout_width="match_parent" + android:layout_height="match_parent"/> + +</LinearLayout>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/layout/frag_rtt_chat.xml b/java/com/android/incallui/rtt/impl/res/layout/frag_rtt_chat.xml new file mode 100644 index 000000000..7ba6a09e3 --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/layout/frag_rtt_chat.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/dialer_theme_color"> + + <include layout="@layout/rtt_banner"/> + + <android.support.v7.widget.RecyclerView + android:id="@+id/rtt_recycler_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingBottom="70dp" + android:clipToPadding="false"/> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="6dp" + android:layout_marginBottom="4dp" + android:layout_marginStart="5dp" + android:layout_marginEnd="4dp" + android:layout_gravity="bottom" + android:orientation="horizontal"> + <EditText + android:id="@+id/rtt_chat_input" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:paddingTop="10dp" + android:paddingBottom="12dp" + android:paddingStart="16dp" + android:paddingEnd="16dp" + android:background="@drawable/input_bubble_background" + android:hint="@string/rtt_input_hint" + android:imeOptions="actionDone" + android:inputType="textMultiLine|text" + android:maxLines="4" + android:minHeight="53dp" + android:textSize="16sp"/> + <ImageButton + android:id="@+id/rtt_chat_submit_button" + android:layout_width="55dp" + android:layout_height="53dp" + android:layout_gravity="bottom" + android:background="@drawable/input_bubble_background" + android:backgroundTint="@color/submit_button_background_color" + android:backgroundTintMode="multiply" + android:contentDescription="@string/content_description_rtt_check_button" + android:src="@drawable/quantum_ic_done_vd_theme_24" + android:tint="@color/submit_button_color"/> + </LinearLayout> + +</FrameLayout>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/layout/rtt_banner.xml b/java/com/android/incallui/rtt/impl/res/layout/rtt_banner.xml new file mode 100644 index 000000000..7d9cd6fc8 --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/layout/rtt_banner.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="56dp" + android:background="#FAFAFA" + android:elevation="3dp"> + <ImageButton + android:id="@+id/rtt_back" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_alignParentStart="true" + android:layout_centerVertical="true" + android:background="@android:color/transparent" + android:contentDescription="@string/content_description_rtt_back_button" + android:src="@drawable/quantum_ic_close_vd_theme_24" + android:tint="#DF000000"/> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_marginTop="8dp" + android:layout_marginBottom="8dp" + android:layout_marginStart="32dp" + android:layout_toEndOf="@id/rtt_back" + android:orientation="vertical"> + <TextView + android:id="@+id/rtt_name_or_number" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:includeFontPadding="false" + android:textAppearance="@style/Dialer.Incall.TextAppearance.RttTitle" + tools:text="Bruce Graham"/> + <Chronometer + android:id="@+id/rtt_timer" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:includeFontPadding="false" + android:textAppearance="@style/Dialer.Incall.TextAppearance.RttTimer" + tools:text="00:09"/> + </LinearLayout> + <ImageButton + android:id="@+id/rtt_hang_up_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="16dp" + android:layout_alignParentEnd="true" + android:layout_centerVertical="true" + android:background="@android:color/transparent" + android:contentDescription="@string/incall_content_description_end_call" + android:src="@drawable/quantum_ic_call_end_vd_theme_24" + android:tint="#FFDF0000"/> + <ImageButton + android:id="@+id/rtt_speaker_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="24dp" + android:layout_centerVertical="true" + android:layout_toStartOf="@id/rtt_hang_up_button" + android:background="@android:color/transparent" + android:contentDescription="@string/incall_content_description_speaker" + android:src="@drawable/quantum_ic_volume_up_vd_theme_24" + android:tint="#DD000000"/> + <ImageButton + android:id="@+id/rtt_mic_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="24dp" + android:layout_centerVertical="true" + android:layout_toStartOf="@id/rtt_speaker_button" + android:background="@android:color/transparent" + android:contentDescription="@string/incall_content_description_unmuted" + android:src="@drawable/quantum_ic_mic_off_vd_theme_24" + android:tint="#DD000000"/> + +</RelativeLayout>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/layout/rtt_chat_list_item.xml b/java/com/android/incallui/rtt/impl/res/layout/rtt_chat_list_item.xml new file mode 100644 index 000000000..54b0f4f6a --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/layout/rtt_chat_list_item.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:orientation="vertical"> + <LinearLayout + android:id="@+id/rtt_chat_message_container" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="horizontal"> + <ImageView + android:id="@+id/rtt_chat_avatar" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_marginStart="8dp" + android:layout_marginEnd="8dp" + android:visibility="gone" + android:contentDescription="@string/content_description_rtt_chat_avatar"/> + <TextView + android:id="@+id/rtt_chat_message" + style="@style/Dialer.Incall.TextAppearance.RttMessage" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingStart="12dp" + android:paddingEnd="12dp" + android:paddingTop="9dp" + android:paddingBottom="9dp" + android:background="@drawable/message_bubble" + android:backgroundTint="@color/message_bubble_color" + android:maxWidth="292dp"/> + </LinearLayout> +</LinearLayout>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/values/colors.xml b/java/com/android/incallui/rtt/impl/res/values/colors.xml new file mode 100644 index 000000000..402cac4a0 --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/values/colors.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<resources> + <color name="rtt_status_bar_color">#E0E0E0</color> +</resources>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/values/dimens.xml b/java/com/android/incallui/rtt/impl/res/values/dimens.xml new file mode 100644 index 000000000..a3f230c08 --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/values/dimens.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<resources> + <dimen name="rtt_message_margin_top">16dp</dimen> + <dimen name="rtt_same_group_message_margin_top">2dp</dimen> +</resources>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/values/strings.xml b/java/com/android/incallui/rtt/impl/res/values/strings.xml new file mode 100644 index 000000000..79377acda --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/values/strings.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<resources> + <!-- Content description for submit chat input button. [CHAR LIMIT=NONE] --> + <string name="content_description_rtt_check_button">Go ahead</string> + + <!-- Content description for button of closing RTT chat window. [CHAR LIMIT=NONE] --> + <string name="content_description_rtt_back_button">Close RTT chat</string> + + <!-- Hint text for input box. [CHAR LIMIT=NONE] --> + <string name="rtt_input_hint">Type a message</string> + + <!-- Content description for avatar of RTT chat message. [CHAR LIMIT=NONE] --> + <string name="content_description_rtt_chat_avatar">Avatar</string> +</resources>
\ No newline at end of file diff --git a/java/com/android/incallui/rtt/impl/res/values/styles.xml b/java/com/android/incallui/rtt/impl/res/values/styles.xml new file mode 100644 index 000000000..b4bb91474 --- /dev/null +++ b/java/com/android/incallui/rtt/impl/res/values/styles.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2018 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License + --> +<resources> + <style name="Dialer.Incall.TextAppearance.RttTitle" parent="Dialer.Incall.TextAppearance"> + <item name="android:fontFamily">sans-serif</item> + <item name="android:textColor">#DD000000</item> + <item name="android:textSize">20sp</item> + </style> + + <style name="Dialer.Incall.TextAppearance.RttMessage" parent="Dialer.Incall.TextAppearance"> + <item name="android:fontFamily">sans-serif</item> + <item name="android:textColor">#DD000000</item> + <item name="android:textSize">16sp</item> + </style> + + <style name="Dialer.Incall.TextAppearance.RttTimer" parent="Dialer.Incall.TextAppearance"> + <item name="android:fontFamily">sans-serif</item> + <item name="android:textColor">#DD000000</item> + <item name="android:textSize">14sp</item> + </style> +</resources>
\ No newline at end of file |