for v2.5.0 Merge branch 'master' into develop
This commit is contained in:
commit
a15756d4ff
|
@ -12,3 +12,10 @@ file_filter = src/quicksy/res/values-<lang>/strings.xml
|
||||||
source_file = src/quicksy/res/values/strings.xml
|
source_file = src/quicksy/res/values/strings.xml
|
||||||
source_lang = en
|
source_lang = en
|
||||||
type = ANDROID
|
type = ANDROID
|
||||||
|
|
||||||
|
[conversations.conversations-strings]
|
||||||
|
file_filter = src/conversations/res/values-<lang>/strings.xml
|
||||||
|
source_file = src/conversations/res/values/strings.xml
|
||||||
|
source_lang = en
|
||||||
|
type = ANDROID
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
### Version 2.5.0
|
||||||
|
* Added channel search via search.jabbercat.org
|
||||||
|
* Reworked onboarding screens
|
||||||
|
* Warn when trying to enter domain address or channel address in Add Contact dialog
|
||||||
|
|
||||||
### Version 2.4.3
|
### Version 2.4.3
|
||||||
* Fixed display of private messages sent from another client
|
* Fixed display of private messages sent from another client
|
||||||
* Fixed backup creation on long time installations
|
* Fixed backup creation on long time installations
|
||||||
|
|
|
@ -6,7 +6,7 @@ buildscript {
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.3.0'
|
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,9 @@ dependencies {
|
||||||
implementation 'org.conscrypt:conscrypt-android:1.3.0'
|
implementation 'org.conscrypt:conscrypt-android:1.3.0'
|
||||||
implementation 'me.drakeet.support:toastcompat:1.1.0'
|
implementation 'me.drakeet.support:toastcompat:1.1.0'
|
||||||
implementation "com.leinardi.android:speed-dial:2.0.1"
|
implementation "com.leinardi.android:speed-dial:2.0.1"
|
||||||
|
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
|
||||||
|
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
|
||||||
|
implementation 'com.google.guava:guava:27.1-android'
|
||||||
quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.10.1'
|
quicksyImplementation 'io.michaelrocks:libphonenumber-android:8.10.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,8 +81,8 @@ android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 323
|
versionCode 326
|
||||||
versionName "2.4.3"
|
versionName "2.5.0"
|
||||||
archivesBaseName += "-$versionName"
|
archivesBaseName += "-$versionName"
|
||||||
applicationId "eu.sum7.conversations"
|
applicationId "eu.sum7.conversations"
|
||||||
resValue "string", "applicationId", applicationId
|
resValue "string", "applicationId", applicationId
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
#Wed Apr 24 10:50:09 CEST 2019
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-5.2-all.zip
|
||||||
|
|
|
@ -18,3 +18,5 @@
|
||||||
-dontwarn org.bouncycastle.cert.dane.**
|
-dontwarn org.bouncycastle.cert.dane.**
|
||||||
-dontwarn rocks.xmpp.addr.**
|
-dontwarn rocks.xmpp.addr.**
|
||||||
-dontwarn com.google.firebase.analytics.connector.AnalyticsConnector
|
-dontwarn com.google.firebase.analytics.connector.AnalyticsConnector
|
||||||
|
-dontwarn java.lang.**
|
||||||
|
-dontwarn javax.lang.**
|
||||||
|
|
|
@ -12,9 +12,13 @@
|
||||||
android:name=".ui.WelcomeActivity"
|
android:name=".ui.WelcomeActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:launchMode="singleTask"/>
|
android:launchMode="singleTask"/>
|
||||||
|
<activity
|
||||||
|
android:name=".ui.PickServerActivity"
|
||||||
|
android:label="@string/create_new_account"
|
||||||
|
android:launchMode="singleTask"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.MagicCreateActivity"
|
android:name=".ui.MagicCreateActivity"
|
||||||
android:label="@string/create_account"
|
android:label="@string/create_new_account"
|
||||||
android:launchMode="singleTask"/>
|
android:launchMode="singleTask"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.ImportBackupActivity"
|
android:name=".ui.ImportBackupActivity"
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
package eu.siacs.conversations.ui;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.databinding.DataBindingUtil;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.R;
|
||||||
|
import eu.siacs.conversations.databinding.ActivityPickServerBinding;
|
||||||
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
|
||||||
|
public class PickServerActivity extends XmppActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refreshUiReal() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onBackendConnected() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
final int theme = findTheme();
|
||||||
|
if (this.mTheme != theme) {
|
||||||
|
recreate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||||
|
if (item.getItemId() == android.R.id.home) {
|
||||||
|
startActivity(new Intent(this, WelcomeActivity.class));
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
startActivity(new Intent(this, WelcomeActivity.class));
|
||||||
|
super.onBackPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onNewIntent(Intent intent) {
|
||||||
|
if (intent != null) {
|
||||||
|
setIntent(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(final Bundle savedInstanceState) {
|
||||||
|
if (getResources().getBoolean(R.bool.portrait_only)) {
|
||||||
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
||||||
|
}
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
ActivityPickServerBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_pick_server);
|
||||||
|
setSupportActionBar((Toolbar) binding.toolbar);
|
||||||
|
configureActionBar(getSupportActionBar());
|
||||||
|
binding.useCim.setOnClickListener(v -> {
|
||||||
|
final Intent intent = new Intent(this, MagicCreateActivity.class);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||||
|
addInviteUri(intent);
|
||||||
|
startActivity(intent);
|
||||||
|
});
|
||||||
|
binding.useOwnProvider.setOnClickListener(v -> {
|
||||||
|
List<Account> accounts = xmppConnectionService.getAccounts();
|
||||||
|
Intent intent = new Intent(this, EditAccountActivity.class);
|
||||||
|
intent.putExtra(EditAccountActivity.EXTRA_FORCE_REGISTER, true);
|
||||||
|
if (accounts.size() == 1) {
|
||||||
|
intent.putExtra("jid", accounts.get(0).getJid().asBareJid().toString());
|
||||||
|
intent.putExtra("init", true);
|
||||||
|
} else if (accounts.size() >= 1) {
|
||||||
|
intent = new Intent(this, ManageAccountActivity.class);
|
||||||
|
}
|
||||||
|
addInviteUri(intent);
|
||||||
|
startActivity(intent);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addInviteUri(Intent intent) {
|
||||||
|
StartConversationActivity.addInviteUri(intent, getIntent());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void launch(AppCompatActivity activity) {
|
||||||
|
Intent intent = new Intent(activity, PickServerActivity.class);
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
activity.startActivity(intent);
|
||||||
|
activity.overridePendingTransition(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,18 +2,19 @@ package eu.siacs.conversations.ui;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.databinding.DataBindingUtil;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v7.app.ActionBar;
|
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
|
import eu.siacs.conversations.databinding.ActivityWelcomeBinding;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
|
||||||
import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
|
import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
|
||||||
|
@ -55,24 +56,18 @@ public class WelcomeActivity extends XmppActivity {
|
||||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
||||||
}
|
}
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.welcome);
|
ActivityWelcomeBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_welcome);
|
||||||
setSupportActionBar(findViewById(R.id.toolbar));
|
setSupportActionBar((Toolbar) binding.toolbar);
|
||||||
final ActionBar ab = getSupportActionBar();
|
configureActionBar(getSupportActionBar(), false);
|
||||||
if (ab != null) {
|
binding.registerNewAccount.setOnClickListener(v -> {
|
||||||
ab.setDisplayShowHomeEnabled(false);
|
final Intent intent = new Intent(this, PickServerActivity.class);
|
||||||
ab.setDisplayHomeAsUpEnabled(false);
|
|
||||||
}
|
|
||||||
final Button createAccount = findViewById(R.id.create_account);
|
|
||||||
createAccount.setOnClickListener(v -> {
|
|
||||||
final Intent intent = new Intent(WelcomeActivity.this, MagicCreateActivity.class);
|
|
||||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
|
||||||
addInviteUri(intent);
|
addInviteUri(intent);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
});
|
});
|
||||||
final Button useOwnProvider = findViewById(R.id.use_own_provider);
|
binding.useExisting.setOnClickListener(v -> {
|
||||||
useOwnProvider.setOnClickListener(v -> {
|
|
||||||
List<Account> accounts = xmppConnectionService.getAccounts();
|
List<Account> accounts = xmppConnectionService.getAccounts();
|
||||||
Intent intent = new Intent(WelcomeActivity.this, EditAccountActivity.class);
|
Intent intent = new Intent(WelcomeActivity.this, EditAccountActivity.class);
|
||||||
|
intent.putExtra(EditAccountActivity.EXTRA_FORCE_REGISTER,false);
|
||||||
if (accounts.size() == 1) {
|
if (accounts.size() == 1) {
|
||||||
intent.putExtra("jid", accounts.get(0).getJid().asBareJid().toString());
|
intent.putExtra("jid", accounts.get(0).getJid().asBareJid().toString());
|
||||||
intent.putExtra("init", true);
|
intent.putExtra("init", true);
|
||||||
|
|
|
@ -9,13 +9,23 @@ import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.ui.ConversationsActivity;
|
import eu.siacs.conversations.ui.ConversationsActivity;
|
||||||
import eu.siacs.conversations.ui.EditAccountActivity;
|
import eu.siacs.conversations.ui.EditAccountActivity;
|
||||||
import eu.siacs.conversations.ui.ManageAccountActivity;
|
import eu.siacs.conversations.ui.ManageAccountActivity;
|
||||||
|
import eu.siacs.conversations.ui.PickServerActivity;
|
||||||
import eu.siacs.conversations.ui.StartConversationActivity;
|
import eu.siacs.conversations.ui.StartConversationActivity;
|
||||||
import eu.siacs.conversations.ui.WelcomeActivity;
|
import eu.siacs.conversations.ui.WelcomeActivity;
|
||||||
|
|
||||||
public class SignupUtils {
|
public class SignupUtils {
|
||||||
|
|
||||||
public static Intent getSignUpIntent(final Activity activity) {
|
public static Intent getSignUpIntent(final Activity activity) {
|
||||||
Intent intent = new Intent(activity, WelcomeActivity.class);
|
return getSignUpIntent(activity, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Intent getSignUpIntent(final Activity activity, final boolean toServerChooser) {
|
||||||
|
Intent intent;
|
||||||
|
if (toServerChooser) {
|
||||||
|
intent = new Intent(activity, PickServerActivity.class);
|
||||||
|
} else {
|
||||||
|
intent = new Intent(activity, WelcomeActivity.class);
|
||||||
|
}
|
||||||
StartConversationActivity.addInviteUri(intent, activity.getIntent());
|
StartConversationActivity.addInviteUri(intent, activity.getIntent());
|
||||||
return intent;
|
return intent;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +37,9 @@ public class SignupUtils {
|
||||||
if (pendingAccount != null) {
|
if (pendingAccount != null) {
|
||||||
intent = new Intent(activity, EditAccountActivity.class);
|
intent = new Intent(activity, EditAccountActivity.class);
|
||||||
intent.putExtra("jid", pendingAccount.getJid().asBareJid().toString());
|
intent.putExtra("jid", pendingAccount.getJid().asBareJid().toString());
|
||||||
|
if (!pendingAccount.isOptionSet(Account.OPTION_MAGIC_CREATE)) {
|
||||||
|
intent.putExtra(EditAccountActivity.EXTRA_FORCE_REGISTER, pendingAccount.isOptionSet(Account.OPTION_REGISTER));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (service.getAccounts().size() == 0) {
|
if (service.getAccounts().size() == 0) {
|
||||||
if (Config.X509_VERIFICATION) {
|
if (Config.X509_VERIFICATION) {
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<include android:id="@+id/toolbar" layout="@layout/toolbar" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fillViewport="true">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/color_background_primary">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linearLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:minHeight="256dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="16dp"
|
||||||
|
android:paddingRight="16dp"
|
||||||
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/pick_a_server"
|
||||||
|
android:textAppearance="@style/TextAppearance.Conversations.Title" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="@string/server_select_text"
|
||||||
|
android:textAppearance="@style/TextAppearance.Conversations.Body1" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/use_cim"
|
||||||
|
style="@style/Widget.Conversations.Button.Borderless"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:text="@string/use_conversations.im"
|
||||||
|
android:textColor="?colorAccent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/use_own_provider"
|
||||||
|
style="@style/Widget.Conversations.Button.Borderless"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:text="@string/use_own_provider"
|
||||||
|
android:textColor="?android:textColorSecondary" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_above="@+id/linearLayout"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/main_logo" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</RelativeLayout>
|
||||||
|
</ScrollView>
|
||||||
|
</LinearLayout>
|
||||||
|
</layout>
|
|
@ -0,0 +1,91 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
layout="@layout/toolbar" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:fillViewport="true">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/color_background_primary">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/linearLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:minHeight="256dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="16dp"
|
||||||
|
android:paddingRight="16dp"
|
||||||
|
android:paddingBottom="10dp">
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/welcome_header"
|
||||||
|
android:textAppearance="@style/TextAppearance.Conversations.Title" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:text="@string/do_you_have_an_account"
|
||||||
|
android:textAppearance="@style/TextAppearance.Conversations.Body1" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/register_new_account"
|
||||||
|
style="@style/Widget.Conversations.Button.Borderless"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:text="@string/create_new_account"
|
||||||
|
android:textColor="?colorAccent" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/use_existing"
|
||||||
|
style="@style/Widget.Conversations.Button.Borderless"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="right"
|
||||||
|
android:text="@string/i_already_have_an_account"
|
||||||
|
android:textColor="?android:textColorSecondary" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_above="@+id/linearLayout"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerHorizontal="true"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/main_logo" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</RelativeLayout>
|
||||||
|
</ScrollView>
|
||||||
|
</LinearLayout>
|
||||||
|
</layout>
|
|
@ -1,78 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<include layout="@layout/toolbar" />
|
|
||||||
|
|
||||||
<ScrollView android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:fillViewport="true">
|
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:background="?attr/color_background_primary">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/linearLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:minHeight="256dp"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingBottom="10dp"
|
|
||||||
android:paddingLeft="16dp"
|
|
||||||
android:paddingRight="16dp">
|
|
||||||
<Space
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_weight="1"/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/welcome_header"
|
|
||||||
android:textAppearance="@style/TextAppearance.Conversations.Title"/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:text="@string/welcome_text"
|
|
||||||
android:textAppearance="@style/TextAppearance.Conversations.Body1"/>
|
|
||||||
<Button
|
|
||||||
android:id="@+id/create_account"
|
|
||||||
style="@style/Widget.Conversations.Button.Borderless"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="right"
|
|
||||||
android:text="@string/create_account"
|
|
||||||
android:textColor="?colorAccent"/>
|
|
||||||
<Button
|
|
||||||
android:id="@+id/use_own_provider"
|
|
||||||
style="@style/Widget.Conversations.Button.Borderless"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="right"
|
|
||||||
android:text="@string/use_own_provider"
|
|
||||||
android:textColor="?android:textColorSecondary"/>
|
|
||||||
</LinearLayout>
|
|
||||||
<RelativeLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_above="@+id/linearLayout"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_alignParentStart="true">
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerHorizontal="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:src="@drawable/main_logo"/>
|
|
||||||
</RelativeLayout>
|
|
||||||
</RelativeLayout>
|
|
||||||
</ScrollView>
|
|
||||||
</LinearLayout>
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="pick_a_server">Wähle deinen XMPP-Provider</string>
|
||||||
|
<string name="use_conversations.im">Benutze conversations.im</string>
|
||||||
|
<string name="create_new_account">Neues Konto erstellen</string>
|
||||||
|
<string name="do_you_have_an_account">Hast du bereits ein XMPP-Konto? Dies kann der Fall sein, wenn du bereits einen anderen XMPP-Client verwendest oder bereits Conversations verwendet hast. Wenn nicht, kannst du jetzt ein neues XMPP-Konto erstellen.\nHinweis: Einige E-Mail-Anbieter bieten auch XMPP-Konten an.</string>
|
||||||
|
<string name="server_select_text">XMPP ist ein anbieterunabhängiges Instant Messaging Netzwerk. Du kannst diesen Client mit jedem beliebigen XMPP-Server nutzen.\nUm es dir leicht zu machen, haben wir die Möglichkeit geschaffen, ein Konto auf conversations.im¹ anzulegen; ein Anbieter, der speziell für die Verwendung mit Conversations geeignet ist.</string>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="pick_a_server">Elige tu proveedor XMPP</string>
|
||||||
|
<string name="use_conversations.im">Usa conversations.im</string>
|
||||||
|
<string name="create_new_account">Crear nueva cuenta</string>
|
||||||
|
<string name="do_you_have_an_account">¿Ya tienes una cuenta XMPP? Este puede ser el caso si ya estás usando un cliente XMPP diferente o has usado Conversations anteriormente. Si no es así, puedes crear una nueva cuenta XMPP ahora mismo.\nConsejo: Algunos proveedores de email también ofrecen una cuenta XMPP.</string>
|
||||||
|
<string name="server_select_text">XMPP es una red de mensajería instantánea independiente del proveedor. Puedes usar este cliente con cualquier servidor XMPP que elijas.\nSin embargo, para tu conveniencia, hacemos de forma sencilla la creación de una cuenta en conversations.im¹; un proveedor especializado para el uso con Conversations </string>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="pick_a_server">Choisissez votre fournisseur XMPP</string>
|
||||||
|
<string name="use_conversations.im">Utiliser conversations.im</string>
|
||||||
|
<string name="create_new_account">Créer un nouveau compte</string>
|
||||||
|
<string name="do_you_have_an_account">Avez-vous déjà un compte XMPP ? Cela peut être le cas si vous utilisez déjà un autre client XMPP ou si vous avez déjà utilisé Conversations auparavant. Sinon, vous pouvez créer un nouveau compte XMPP dès maintenant. Remarque : Certains fournisseurs de messagerie proposent également des comptes XMPP.</string>
|
||||||
|
<string name="server_select_text">XMPP est un réseau de messagerie instantanée indépendant du fournisseur. Vous pouvez utiliser ce client avec n\'importe quel serveur XMPP de votre choix. Toutefois, pour votre commodité, nous avons facilité la création d\'un compte sur conversations.im¹ ; un fournisseur spécialement conçu pour l\'utilisation avec Conversations.</string>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="pick_a_server">Válassza ki az XMPP szolgáltatóját</string>
|
||||||
|
<string name="use_conversations.im">conversations.im használata</string>
|
||||||
|
<string name="create_new_account">Új fiók létrehozása</string>
|
||||||
|
<string name="do_you_have_an_account">Már rendelkezik XMPP fiókkal? Ez az eset állhat fenn, ha már egy másik XMPP klienst használ vagy ha már korábban használta a Conversations-t. Ha nem, akkor most létrehozhat egy új XMPP fiókot.\nTipp: Egyes e-mail szolgáltatók is biztosítanak XMPP fiókokat is.</string>
|
||||||
|
<string name="server_select_text">Az XMPP egy szolgáltató független, azonnali üzenetküldő hálózat. Ezt az ügyfél programot bármelyik XMPP szerverhez használhatja.\nDe a könnyebbség kedvéért létrehozhat egy fiókot a conversations.im¹ szolgáltatón is; ami kifejezetten a Conversations programmal való használatra lett tervezve.</string>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="pick_a_server">Scegli il tuo provider XMPP</string>
|
||||||
|
<string name="use_conversations.im">Usa conversations.im</string>
|
||||||
|
<string name="create_new_account">Crea un nuovo account</string>
|
||||||
|
<string name="do_you_have_an_account">Possiedi già un account XMPP? Questo succede se stai già usando un diverso client XMPP o hai già usato prima Conversations. In caso negativo puoi creare un account XMPP adesso.
|
||||||
|
Suggerimento: alcuni provider di email forniscono anche un account XMPP.</string>
|
||||||
|
<string name="server_select_text">XMPP è una rete di instant messaging indipendente dal provider. Puoi usare questo client con qualsiasi server XMPP.
|
||||||
|
In ogni caso per facilitare puoi creare facilmente un account su conversations.im, un provider pensato apposta per essere usato con Conversations.</string>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="pick_a_server">Kies je XMPP-dienst</string>
|
||||||
|
<string name="use_conversations.im">Conversations.im gebruiken</string>
|
||||||
|
<string name="create_new_account">Nieuwe account registreren</string>
|
||||||
|
<string name="do_you_have_an_account">Heb je al een XMPP-account? Als je al een andere XMPP-cliënt gebruikt, of Conversations vroeger al eens hebt gebruikt, is dit waarschijnlijk het geval. Zo niet, kan je nu een nieuwe XMPP-account aanmaken.\nTip: sommige e-mailproviders bieden ook XMPP-accounts aan.</string>
|
||||||
|
<string name="server_select_text">XMPP is een provider-onafhankelijk berichtennetwerk. Je kan deze cliënt gebruiken met eender welke XMPP-server.\nOm het je gemakkelijker te maken kun je simpelweg een account aanmaken op conversations.im¹; een provider speciaal geschikt voor Conversations.</string>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="pick_a_server">Selecione o seu provedor XMPP</string>
|
||||||
|
</resources>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="pick_a_server">Alegeți-vă furnizorul XMPP</string>
|
||||||
|
<string name="use_conversations.im">Folosește conversations.im</string>
|
||||||
|
<string name="create_new_account">Creează un cont nou</string>
|
||||||
|
<string name="do_you_have_an_account">Aveți deja un cont XMPP? S-ar putea să fie așa dacă deja utilizați un alt client XMPP sau dacă ați folosit Conversations în trecut. Dacă nu, puteți crea un cont nou XMPP chiar acum.\nIdee: Unii furnizori de e-mail oferă de asemenea și conturi XMPP.</string>
|
||||||
|
<string name="server_select_text">XMPP este o rețea de mesagerie instant ce nu depinde de un anumit furnizor. Aveți posibilitatea să utilizați acest client cu orice server XMPP doriți.\nTotuși, pentru confortul dumneavoastră, am facilitat crearea unui cont pe conversations.im¹; un furnizor potrivit pentru utilizarea cu aplicația Conversations.</string>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="pick_a_server">Pick your XMPP provider</string>
|
||||||
|
<string name="use_conversations.im">Use conversations.im</string>
|
||||||
|
<string name="create_new_account">Create new account</string>
|
||||||
|
<string name="do_you_have_an_account">Do you already have an XMPP account? This might be the case if you are already using a different XMPP client or have used Conversations before. If not you can create a new XMPP account right now.\nHint: Some email providers also provide XMPP accounts.</string>
|
||||||
|
<string name="server_select_text">XMPP is a provider independent instant messaging network. You can use this client with what ever XMPP server you choose.\nHowever for your convenience we made it easy to create an account on conversations.im¹; a provider specially suited for the use with Conversations.</string>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -283,6 +283,7 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.MucUsersActivity"
|
android:name=".ui.MucUsersActivity"
|
||||||
android:label="@string/group_chat_members" />
|
android:label="@string/group_chat_members" />
|
||||||
|
<activity android:label="@string/discover_channels" android:name=".ui.ChannelDiscoveryActivity"/>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -40,6 +40,9 @@ public final class Config {
|
||||||
public static final String DOMAIN_LOCK = null; //only allow account creation for this domain
|
public static final String DOMAIN_LOCK = null; //only allow account creation for this domain
|
||||||
public static final String MAGIC_CREATE_DOMAIN = "chat.sum7.eu";
|
public static final String MAGIC_CREATE_DOMAIN = "chat.sum7.eu";
|
||||||
public static final String QUICKSY_DOMAIN = "quicksy.im";
|
public static final String QUICKSY_DOMAIN = "quicksy.im";
|
||||||
|
|
||||||
|
public static final String CHANNEL_DISCOVERY = "https://search.jabbercat.org";
|
||||||
|
|
||||||
public static final boolean DISALLOW_REGISTRATION_IN_UI = false; //hide the register checkbox
|
public static final boolean DISALLOW_REGISTRATION_IN_UI = false; //hide the register checkbox
|
||||||
|
|
||||||
public static final boolean USE_RANDOM_RESOURCE_ON_EVERY_BIND = false;
|
public static final boolean USE_RANDOM_RESOURCE_ON_EVERY_BIND = false;
|
||||||
|
|
|
@ -1326,7 +1326,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean success;
|
final boolean success;
|
||||||
if (message.getType() == Message.TYPE_PRIVATE) {
|
if (message.isPrivateMessage()) {
|
||||||
success = buildHeader(axolotlMessage, message.getTrueCounterpart());
|
success = buildHeader(axolotlMessage, message.getTrueCounterpart());
|
||||||
} else {
|
} else {
|
||||||
success = buildHeader(axolotlMessage, (Conversation) message.getConversation());
|
success = buildHeader(axolotlMessage, (Conversation) message.getConversation());
|
||||||
|
|
|
@ -60,6 +60,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
||||||
private static final String ATTRIBUTE_NEXT_MESSAGE_TIMESTAMP = "next_message_timestamp";
|
private static final String ATTRIBUTE_NEXT_MESSAGE_TIMESTAMP = "next_message_timestamp";
|
||||||
private static final String ATTRIBUTE_CRYPTO_TARGETS = "crypto_targets";
|
private static final String ATTRIBUTE_CRYPTO_TARGETS = "crypto_targets";
|
||||||
private static final String ATTRIBUTE_NEXT_ENCRYPTION = "next_encryption";
|
private static final String ATTRIBUTE_NEXT_ENCRYPTION = "next_encryption";
|
||||||
|
private static final String ATTRIBUTE_CORRECTING_MESSAGE = "correcting_message";
|
||||||
static final String ATTRIBUTE_MEMBERS_ONLY = "members_only";
|
static final String ATTRIBUTE_MEMBERS_ONLY = "members_only";
|
||||||
static final String ATTRIBUTE_MODERATED = "moderated";
|
static final String ATTRIBUTE_MODERATED = "moderated";
|
||||||
static final String ATTRIBUTE_NON_ANONYMOUS = "non_anonymous";
|
static final String ATTRIBUTE_NON_ANONYMOUS = "non_anonymous";
|
||||||
|
@ -82,7 +83,6 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
||||||
private ChatState mOutgoingChatState = Config.DEFAULT_CHATSTATE;
|
private ChatState mOutgoingChatState = Config.DEFAULT_CHATSTATE;
|
||||||
private ChatState mIncomingChatState = Config.DEFAULT_CHATSTATE;
|
private ChatState mIncomingChatState = Config.DEFAULT_CHATSTATE;
|
||||||
private String mFirstMamReference = null;
|
private String mFirstMamReference = null;
|
||||||
private Message correctingMessage;
|
|
||||||
|
|
||||||
public Conversation(final String name, final Account account, final Jid contactJid,
|
public Conversation(final String name, final Account account, final Jid contactJid,
|
||||||
final int mode) {
|
final int mode) {
|
||||||
|
@ -425,12 +425,13 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setCorrectingMessage(Message correctingMessage) {
|
public boolean setCorrectingMessage(Message correctingMessage) {
|
||||||
this.correctingMessage = correctingMessage;
|
setAttribute(ATTRIBUTE_CORRECTING_MESSAGE,correctingMessage == null ? null : correctingMessage.getUuid());
|
||||||
return correctingMessage == null && draftMessage != null;
|
return correctingMessage == null && draftMessage != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message getCorrectingMessage() {
|
public Message getCorrectingMessage() {
|
||||||
return this.correctingMessage;
|
final String uuid = getAttribute(ATTRIBUTE_CORRECTING_MESSAGE);
|
||||||
|
return uuid == null ? null : findSentMessageWithUuid(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean withSelf() {
|
public boolean withSelf() {
|
||||||
|
@ -485,7 +486,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
||||||
final Message message = messages.get(i);
|
final Message message = messages.get(i);
|
||||||
if (message.getStatus() <= Message.STATUS_RECEIVED
|
if (message.getStatus() <= Message.STATUS_RECEIVED
|
||||||
&& (message.markable || isPrivateAndNonAnonymousMuc)
|
&& (message.markable || isPrivateAndNonAnonymousMuc)
|
||||||
&& message.getType() != Message.TYPE_PRIVATE) {
|
&& !message.isPrivateMessage()) {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -747,7 +748,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
|
||||||
synchronized (this.messages) {
|
synchronized (this.messages) {
|
||||||
for (int i = this.messages.size() - 1; i >= 0; --i) {
|
for (int i = this.messages.size() - 1; i >= 0; --i) {
|
||||||
final Message message = this.messages.get(i);
|
final Message message = this.messages.get(i);
|
||||||
if (message.getType() == Message.TYPE_PRIVATE) {
|
if (message.isPrivateMessage()) {
|
||||||
continue; //it's unsafe to use private messages as anchor. They could be coming from user archive
|
continue; //it's unsafe to use private messages as anchor. They could be coming from user archive
|
||||||
}
|
}
|
||||||
if (message.getStatus() == Message.STATUS_RECEIVED || message.isCarbon() || message.getServerMsgId() != null) {
|
if (message.getStatus() == Message.STATUS_RECEIVED || message.isCarbon() || message.getServerMsgId() != null) {
|
||||||
|
|
|
@ -57,6 +57,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
||||||
public static final int TYPE_FILE = 2;
|
public static final int TYPE_FILE = 2;
|
||||||
public static final int TYPE_STATUS = 3;
|
public static final int TYPE_STATUS = 3;
|
||||||
public static final int TYPE_PRIVATE = 4;
|
public static final int TYPE_PRIVATE = 4;
|
||||||
|
public static final int TYPE_PRIVATE_FILE = 5;
|
||||||
|
|
||||||
public static final String CONVERSATION = "conversationUuid";
|
public static final String CONVERSATION = "conversationUuid";
|
||||||
public static final String COUNTERPART = "counterpart";
|
public static final String COUNTERPART = "counterpart";
|
||||||
|
@ -495,7 +496,7 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean similar(Message message) {
|
boolean similar(Message message) {
|
||||||
if (type != TYPE_PRIVATE && this.serverMsgId != null && message.getServerMsgId() != null) {
|
if (!isPrivateMessage() && this.serverMsgId != null && message.getServerMsgId() != null) {
|
||||||
return this.serverMsgId.equals(message.getServerMsgId()) || Edited.wasPreviouslyEditedServerMsgId(edits, message.getServerMsgId());
|
return this.serverMsgId.equals(message.getServerMsgId()) || Edited.wasPreviouslyEditedServerMsgId(edits, message.getServerMsgId());
|
||||||
} else if (Edited.wasPreviouslyEditedServerMsgId(edits, message.getServerMsgId())) {
|
} else if (Edited.wasPreviouslyEditedServerMsgId(edits, message.getServerMsgId())) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -837,8 +838,12 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
||||||
this.mPreviousMessage = null;
|
this.mPreviousMessage = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPrivateMessage() {
|
||||||
|
return type == TYPE_PRIVATE || type == TYPE_PRIVATE_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isFileOrImage() {
|
public boolean isFileOrImage() {
|
||||||
return type == TYPE_FILE || type == TYPE_IMAGE;
|
return type == TYPE_FILE || type == TYPE_IMAGE || type == TYPE_PRIVATE_FILE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasFileOnRemoteHost() {
|
public boolean hasFileOnRemoteHost() {
|
||||||
|
@ -915,4 +920,31 @@ public class Message extends AbstractEntity implements AvatarService.Avatarable
|
||||||
}
|
}
|
||||||
return encryption;
|
return encryption;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean configurePrivateMessage(final Message message) {
|
||||||
|
return configurePrivateMessage(message, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean configurePrivateFileMessage(final Message message) {
|
||||||
|
return configurePrivateMessage(message, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean configurePrivateMessage(final Message message, final boolean isFile) {
|
||||||
|
final Conversation conversation;
|
||||||
|
if (message.conversation instanceof Conversation) {
|
||||||
|
conversation = (Conversation) message.conversation;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (conversation.getMode() == Conversation.MODE_MULTI) {
|
||||||
|
final Jid nextCounterpart = conversation.getNextCounterpart();
|
||||||
|
if (nextCounterpart != null) {
|
||||||
|
message.setCounterpart(nextCounterpart);
|
||||||
|
message.setTrueCounterpart(conversation.getMucOptions().getTrueCounterpart(nextCounterpart));
|
||||||
|
message.setType(isFile ? Message.TYPE_PRIVATE_FILE : Message.TYPE_PRIVATE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -415,7 +415,7 @@ public class IqGenerator extends AbstractGenerator {
|
||||||
register.setFrom(account.getJid().asBareJid());
|
register.setFrom(account.getJid().asBareJid());
|
||||||
register.setTo(Jid.of(account.getServer()));
|
register.setTo(Jid.of(account.getServer()));
|
||||||
register.setId(id);
|
register.setId(id);
|
||||||
Element query = register.query("jabber:iq:register");
|
Element query = register.query(Namespace.REGISTER);
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
query.addChild(data);
|
query.addChild(data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package eu.siacs.conversations.generator;
|
package eu.siacs.conversations.generator;
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -13,7 +11,6 @@ import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||||
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage;
|
import eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.entities.Contact;
|
|
||||||
import eu.siacs.conversations.entities.Conversation;
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
import eu.siacs.conversations.entities.Message;
|
import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.http.P1S3UrlStreamHandler;
|
import eu.siacs.conversations.http.P1S3UrlStreamHandler;
|
||||||
|
@ -43,7 +40,7 @@ public class MessageGenerator extends AbstractGenerator {
|
||||||
if (this.mXmppConnectionService.indicateReceived() && !isWithSelf) {
|
if (this.mXmppConnectionService.indicateReceived() && !isWithSelf) {
|
||||||
packet.addChild("request", "urn:xmpp:receipts");
|
packet.addChild("request", "urn:xmpp:receipts");
|
||||||
}
|
}
|
||||||
} else if (message.getType() == Message.TYPE_PRIVATE) { //TODO files and images might be private as well
|
} else if (message.isPrivateMessage()) {
|
||||||
packet.setTo(message.getCounterpart());
|
packet.setTo(message.getCounterpart());
|
||||||
packet.setType(MessagePacket.TYPE_CHAT);
|
packet.setType(MessagePacket.TYPE_CHAT);
|
||||||
packet.addChild("x", "http://jabber.org/protocol/muc#user");
|
packet.addChild("x", "http://jabber.org/protocol/muc#user");
|
||||||
|
@ -54,7 +51,7 @@ public class MessageGenerator extends AbstractGenerator {
|
||||||
packet.setTo(message.getCounterpart().asBareJid());
|
packet.setTo(message.getCounterpart().asBareJid());
|
||||||
packet.setType(MessagePacket.TYPE_GROUPCHAT);
|
packet.setType(MessagePacket.TYPE_GROUPCHAT);
|
||||||
}
|
}
|
||||||
if (conversation.isSingleOrPrivateAndNonAnonymous() && message.getType() != Message.TYPE_PRIVATE) {
|
if (conversation.isSingleOrPrivateAndNonAnonymous() && !message.isPrivateMessage()) {
|
||||||
packet.addChild("markable", "urn:xmpp:chat-markers:0");
|
packet.addChild("markable", "urn:xmpp:chat-markers:0");
|
||||||
}
|
}
|
||||||
packet.setFrom(account.getJid());
|
packet.setFrom(account.getJid());
|
||||||
|
|
|
@ -442,7 +442,8 @@ public class HttpDownloadConnection implements Transferable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateImageBounds() {
|
private void updateImageBounds() {
|
||||||
message.setType(Message.TYPE_FILE);
|
final boolean privateMessage = message.isPrivateMessage();
|
||||||
|
message.setType(privateMessage ? Message.TYPE_PRIVATE_FILE : Message.TYPE_FILE);
|
||||||
final URL url;
|
final URL url;
|
||||||
final String ref = mUrl.getRef();
|
final String ref = mUrl.getRef();
|
||||||
if (method == Method.P1_S3) {
|
if (method == Method.P1_S3) {
|
||||||
|
|
|
@ -216,7 +216,9 @@ public class HttpUploadConnection implements Transferable {
|
||||||
mXmppConnectionService.getFileBackend().updateFileParams(message, get);
|
mXmppConnectionService.getFileBackend().updateFileParams(message, get);
|
||||||
mXmppConnectionService.getFileBackend().updateMediaScanner(file);
|
mXmppConnectionService.getFileBackend().updateMediaScanner(file);
|
||||||
finish();
|
finish();
|
||||||
message.setCounterpart(message.getConversation().getJid().asBareJid());
|
if (!message.isPrivateMessage()) {
|
||||||
|
message.setCounterpart(message.getConversation().getJid().asBareJid());
|
||||||
|
}
|
||||||
mXmppConnectionService.resendMessage(message, delayed);
|
mXmppConnectionService.resendMessage(message, delayed);
|
||||||
} else {
|
} else {
|
||||||
Log.d(Config.LOGTAG,"http upload failed because response code was "+code);
|
Log.d(Config.LOGTAG,"http upload failed because response code was "+code);
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
package eu.siacs.conversations.http.services;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.services.AvatarService;
|
||||||
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.Body;
|
||||||
|
import retrofit2.http.GET;
|
||||||
|
import retrofit2.http.POST;
|
||||||
|
import retrofit2.http.Query;
|
||||||
|
import rocks.xmpp.addr.Jid;
|
||||||
|
|
||||||
|
public interface MuclumbusService {
|
||||||
|
|
||||||
|
@GET("/api/1.0/rooms/unsafe")
|
||||||
|
Call<Rooms> getRooms(@Query("p") int page);
|
||||||
|
|
||||||
|
@POST("/api/1.0/search")
|
||||||
|
Call<SearchResult> search(@Body SearchRequest searchRequest);
|
||||||
|
|
||||||
|
class Rooms {
|
||||||
|
int page;
|
||||||
|
int total;
|
||||||
|
int pages;
|
||||||
|
public List<Room> items;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Room implements AvatarService.Avatarable {
|
||||||
|
|
||||||
|
public String address;
|
||||||
|
public String name;
|
||||||
|
public String description;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Jid getRoom() {
|
||||||
|
try {
|
||||||
|
return Jid.of(address);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAvatarBackgroundColor() {
|
||||||
|
Jid room = getRoom();
|
||||||
|
return UIHelper.getColorForName(room != null ? room.asBareJid().toEscapedString() : name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Room room = (Room) o;
|
||||||
|
return Objects.equal(address, room.address) &&
|
||||||
|
Objects.equal(name, room.name) &&
|
||||||
|
Objects.equal(description, room.description);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(address, name, description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SearchRequest {
|
||||||
|
|
||||||
|
public Set<String> keywords;
|
||||||
|
|
||||||
|
public SearchRequest(String keyword) {
|
||||||
|
this.keywords = Collections.singleton(keyword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SearchResult {
|
||||||
|
|
||||||
|
public Result result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Result {
|
||||||
|
|
||||||
|
public List<Room> items;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -551,7 +551,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
||||||
mXmppConnectionService.updateMessage(replacedMessage, uuid);
|
mXmppConnectionService.updateMessage(replacedMessage, uuid);
|
||||||
if (mXmppConnectionService.confirmMessages()
|
if (mXmppConnectionService.confirmMessages()
|
||||||
&& replacedMessage.getStatus() == Message.STATUS_RECEIVED
|
&& replacedMessage.getStatus() == Message.STATUS_RECEIVED
|
||||||
&& (replacedMessage.trusted() || replacedMessage.getType() == Message.TYPE_PRIVATE)
|
&& (replacedMessage.trusted() || replacedMessage.isPrivateMessage()) //TODO do we really want to send receipts for all PMs?
|
||||||
&& remoteMsgId != null
|
&& remoteMsgId != null
|
||||||
&& !selfAddressed
|
&& !selfAddressed
|
||||||
&& !isTypeGroupChat) {
|
&& !isTypeGroupChat) {
|
||||||
|
@ -577,7 +577,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean checkForDuplicates = (isTypeGroupChat && packet.hasChild("delay", "urn:xmpp:delay"))
|
boolean checkForDuplicates = (isTypeGroupChat && packet.hasChild("delay", "urn:xmpp:delay"))
|
||||||
|| message.getType() == Message.TYPE_PRIVATE
|
|| message.isPrivateMessage()
|
||||||
|| message.getServerMsgId() != null
|
|| message.getServerMsgId() != null
|
||||||
|| (query == null && mXmppConnectionService.getMessageArchiveService().isCatchupInProgress(conversation));
|
|| (query == null && mXmppConnectionService.getMessageArchiveService().isCatchupInProgress(conversation));
|
||||||
if (checkForDuplicates) {
|
if (checkForDuplicates) {
|
||||||
|
@ -637,7 +637,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
||||||
|
|
||||||
if (mXmppConnectionService.confirmMessages()
|
if (mXmppConnectionService.confirmMessages()
|
||||||
&& message.getStatus() == Message.STATUS_RECEIVED
|
&& message.getStatus() == Message.STATUS_RECEIVED
|
||||||
&& (message.trusted() || message.getType() == Message.TYPE_PRIVATE)
|
&& (message.trusted() || message.isPrivateMessage())
|
||||||
&& remoteMsgId != null
|
&& remoteMsgId != null
|
||||||
&& !selfAddressed
|
&& !selfAddressed
|
||||||
&& !isTypeGroupChat) {
|
&& !isTypeGroupChat) {
|
||||||
|
|
|
@ -811,14 +811,14 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
if (internal) {
|
if (internal) {
|
||||||
final String name = file.getName();
|
final String name = file.getName();
|
||||||
if (name.endsWith(".pgp")) {
|
if (name.endsWith(".pgp")) {
|
||||||
selection = "(" + Message.RELATIVE_FILE_PATH + " IN(?,?) OR (" + Message.RELATIVE_FILE_PATH + "=? and encryption in(1,4))) and type in (1,2)";
|
selection = "(" + Message.RELATIVE_FILE_PATH + " IN(?,?) OR (" + Message.RELATIVE_FILE_PATH + "=? and encryption in(1,4))) and type in (1,2,5)";
|
||||||
selectionArgs = new String[]{file.getAbsolutePath(), name, name.substring(0, name.length() - 4)};
|
selectionArgs = new String[]{file.getAbsolutePath(), name, name.substring(0, name.length() - 4)};
|
||||||
} else {
|
} else {
|
||||||
selection = Message.RELATIVE_FILE_PATH + " IN(?,?) and type in (1,2)";
|
selection = Message.RELATIVE_FILE_PATH + " IN(?,?) and type in (1,2,5)";
|
||||||
selectionArgs = new String[]{file.getAbsolutePath(), name};
|
selectionArgs = new String[]{file.getAbsolutePath(), name};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
selection = Message.RELATIVE_FILE_PATH + "=? and type in (1,2)";
|
selection = Message.RELATIVE_FILE_PATH + "=? and type in (1,2,5)";
|
||||||
selectionArgs = new String[]{file.getAbsolutePath()};
|
selectionArgs = new String[]{file.getAbsolutePath()};
|
||||||
}
|
}
|
||||||
final List<String> uuids = new ArrayList<>();
|
final List<String> uuids = new ArrayList<>();
|
||||||
|
@ -861,7 +861,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
|
|
||||||
public List<FilePathInfo> getFilePathInfo() {
|
public List<FilePathInfo> getFilePathInfo() {
|
||||||
final SQLiteDatabase db = this.getReadableDatabase();
|
final SQLiteDatabase db = this.getReadableDatabase();
|
||||||
final Cursor cursor = db.query(Message.TABLENAME, new String[]{Message.UUID, Message.RELATIVE_FILE_PATH, Message.DELETED}, "type in (1,2) and "+Message.RELATIVE_FILE_PATH+" is not null", null, null, null, null);
|
final Cursor cursor = db.query(Message.TABLENAME, new String[]{Message.UUID, Message.RELATIVE_FILE_PATH, Message.DELETED}, "type in (1,2,5) and "+Message.RELATIVE_FILE_PATH+" is not null", null, null, null, null);
|
||||||
final List<FilePathInfo> list = new ArrayList<>();
|
final List<FilePathInfo> list = new ArrayList<>();
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
list.add(new FilePathInfo(cursor.getString(0), cursor.getString(1), cursor.getInt(2) > 0));
|
list.add(new FilePathInfo(cursor.getString(0), cursor.getString(1), cursor.getInt(2) > 0));
|
||||||
|
@ -874,7 +874,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
|
||||||
|
|
||||||
public List<FilePath> getRelativeFilePaths(String account, Jid jid, int limit) {
|
public List<FilePath> getRelativeFilePaths(String account, Jid jid, int limit) {
|
||||||
SQLiteDatabase db = this.getReadableDatabase();
|
SQLiteDatabase db = this.getReadableDatabase();
|
||||||
final String SQL = "select uuid,relativeFilePath from messages where type in (1,2) and deleted=0 and "+Message.RELATIVE_FILE_PATH+" is not null and conversationUuid=(select uuid from conversations where accountUuid=? and (contactJid=? or contactJid like ?)) order by timeSent desc";
|
final String SQL = "select uuid,relativeFilePath from messages where type in (1,2,5) and deleted=0 and "+Message.RELATIVE_FILE_PATH+" is not null and conversationUuid=(select uuid from conversations where accountUuid=? and (contactJid=? or contactJid like ?)) order by timeSent desc";
|
||||||
final String[] args = {account, jid.toEscapedString(), jid.toEscapedString() + "/%"};
|
final String[] args = {account, jid.toEscapedString(), jid.toEscapedString() + "/%"};
|
||||||
Cursor cursor = db.rawQuery(SQL + (limit > 0 ? " limit " + String.valueOf(limit) : ""), args);
|
Cursor cursor = db.rawQuery(SQL + (limit > 0 ? " limit " + String.valueOf(limit) : ""), args);
|
||||||
List<FilePath> filesPaths = new ArrayList<>();
|
List<FilePath> filesPaths = new ArrayList<>();
|
||||||
|
|
|
@ -1178,6 +1178,7 @@ public class FileBackend {
|
||||||
public void updateFileParams(Message message, URL url) {
|
public void updateFileParams(Message message, URL url) {
|
||||||
DownloadableFile file = getFile(message);
|
DownloadableFile file = getFile(message);
|
||||||
final String mime = file.getMimeType();
|
final String mime = file.getMimeType();
|
||||||
|
final boolean privateMessage = message.isPrivateMessage();
|
||||||
final boolean image = message.getType() == Message.TYPE_IMAGE || (mime != null && mime.startsWith("image/"));
|
final boolean image = message.getType() == Message.TYPE_IMAGE || (mime != null && mime.startsWith("image/"));
|
||||||
final boolean video = mime != null && mime.startsWith("video/");
|
final boolean video = mime != null && mime.startsWith("video/");
|
||||||
final boolean audio = mime != null && mime.startsWith("audio/");
|
final boolean audio = mime != null && mime.startsWith("audio/");
|
||||||
|
@ -1201,7 +1202,7 @@ public class FileBackend {
|
||||||
}
|
}
|
||||||
message.setBody(body.toString());
|
message.setBody(body.toString());
|
||||||
message.setDeleted(false);
|
message.setDeleted(false);
|
||||||
message.setType(image ? Message.TYPE_IMAGE : Message.TYPE_FILE);
|
message.setType(privateMessage ? Message.TYPE_PRIVATE_FILE : (image ? Message.TYPE_IMAGE : Message.TYPE_FILE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package eu.siacs.conversations.services;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
|
@ -14,7 +13,6 @@ import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.support.annotation.ColorInt;
|
import android.support.annotation.ColorInt;
|
||||||
import android.support.annotation.DrawableRes;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.content.res.ResourcesCompat;
|
import android.support.v4.content.res.ResourcesCompat;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
@ -39,10 +37,10 @@ import eu.siacs.conversations.entities.Conversational;
|
||||||
import eu.siacs.conversations.entities.ListItem;
|
import eu.siacs.conversations.entities.ListItem;
|
||||||
import eu.siacs.conversations.entities.Message;
|
import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.entities.MucOptions;
|
import eu.siacs.conversations.entities.MucOptions;
|
||||||
|
import eu.siacs.conversations.http.services.MuclumbusService;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
|
import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded;
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
import eu.siacs.conversations.xmpp.pep.Avatar;
|
|
||||||
import rocks.xmpp.addr.Jid;
|
import rocks.xmpp.addr.Jid;
|
||||||
|
|
||||||
public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
|
public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
|
@ -82,11 +80,22 @@ public class AvatarService implements OnAdvancedStreamFeaturesLoaded {
|
||||||
return get((ListItem) avatarable, size, cachedOnly);
|
return get((ListItem) avatarable, size, cachedOnly);
|
||||||
} else if (avatarable instanceof MucOptions.User) {
|
} else if (avatarable instanceof MucOptions.User) {
|
||||||
return get((MucOptions.User) avatarable, size, cachedOnly);
|
return get((MucOptions.User) avatarable, size, cachedOnly);
|
||||||
|
} else if (avatarable instanceof MuclumbusService.Room) {
|
||||||
|
return get((MuclumbusService.Room) avatarable, size, cachedOnly);
|
||||||
}
|
}
|
||||||
throw new AssertionError("AvatarService does not know how to generate avatar from "+avatarable.getClass().getName());
|
throw new AssertionError("AvatarService does not know how to generate avatar from "+avatarable.getClass().getName());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Bitmap get(final MuclumbusService.Room result, final int size, boolean cacheOnly) {
|
||||||
|
final Jid room = result.getRoom();
|
||||||
|
Conversation conversation = room != null ? mXmppConnectionService.findFirstMuc(room) : null;
|
||||||
|
if (conversation != null) {
|
||||||
|
return get(conversation,size,cacheOnly);
|
||||||
|
}
|
||||||
|
return get(result.getName(), room != null ? room.asBareJid().toEscapedString() : result.getName(), size, cacheOnly);
|
||||||
|
}
|
||||||
|
|
||||||
private Bitmap get(final Contact contact, final int size, boolean cachedOnly) {
|
private Bitmap get(final Contact contact, final int size, boolean cachedOnly) {
|
||||||
if (contact.isSelf()) {
|
if (contact.isSelf()) {
|
||||||
return get(contact.getAccount(), size, cachedOnly);
|
return get(contact.getAccount(), size, cachedOnly);
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
package eu.siacs.conversations.services;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.Config;
|
||||||
|
import eu.siacs.conversations.http.HttpConnectionManager;
|
||||||
|
import eu.siacs.conversations.http.services.MuclumbusService;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
import retrofit2.Retrofit;
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory;
|
||||||
|
|
||||||
|
public class ChannelDiscoveryService {
|
||||||
|
|
||||||
|
private final XmppConnectionService service;
|
||||||
|
|
||||||
|
|
||||||
|
private MuclumbusService muclumbusService;
|
||||||
|
|
||||||
|
private final Cache<String, List<MuclumbusService.Room>> cache;
|
||||||
|
|
||||||
|
public ChannelDiscoveryService(XmppConnectionService service) {
|
||||||
|
this.service = service;
|
||||||
|
this.cache = CacheBuilder.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initializeMuclumbusService() {
|
||||||
|
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||||
|
if (service.useTorToConnect()) {
|
||||||
|
try {
|
||||||
|
builder.proxy(HttpConnectionManager.getProxy());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Unable to use Tor proxy", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Retrofit retrofit = new Retrofit.Builder()
|
||||||
|
.client(builder.build())
|
||||||
|
.baseUrl(Config.CHANNEL_DISCOVERY)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.callbackExecutor(Executors.newSingleThreadExecutor())
|
||||||
|
.build();
|
||||||
|
this.muclumbusService = retrofit.create(MuclumbusService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void discover(String query, OnChannelSearchResultsFound onChannelSearchResultsFound) {
|
||||||
|
final boolean all = query == null || query.trim().isEmpty();
|
||||||
|
Log.d(Config.LOGTAG, "discover channels. query=" + query);
|
||||||
|
List<MuclumbusService.Room> result = cache.getIfPresent(all ? "" : query);
|
||||||
|
if (result != null) {
|
||||||
|
onChannelSearchResultsFound.onChannelSearchResultsFound(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (all) {
|
||||||
|
discoverChannels(onChannelSearchResultsFound);
|
||||||
|
} else {
|
||||||
|
discoverChannels(query, onChannelSearchResultsFound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void discoverChannels(OnChannelSearchResultsFound listener) {
|
||||||
|
Call<MuclumbusService.Rooms> call = muclumbusService.getRooms(1);
|
||||||
|
try {
|
||||||
|
call.enqueue(new Callback<MuclumbusService.Rooms>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<MuclumbusService.Rooms> call, Response<MuclumbusService.Rooms> response) {
|
||||||
|
final MuclumbusService.Rooms body = response.body();
|
||||||
|
if (body == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cache.put("", body.items);
|
||||||
|
listener.onChannelSearchResultsFound(body.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<MuclumbusService.Rooms> call, Throwable throwable) {
|
||||||
|
Log.d(Config.LOGTAG, "Unable to query muclumbus on "+Config.CHANNEL_DISCOVERY, throwable);
|
||||||
|
listener.onChannelSearchResultsFound(Collections.emptyList());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void discoverChannels(final String query, OnChannelSearchResultsFound listener) {
|
||||||
|
Call<MuclumbusService.SearchResult> searchResultCall = muclumbusService.search(new MuclumbusService.SearchRequest(query));
|
||||||
|
|
||||||
|
searchResultCall.enqueue(new Callback<MuclumbusService.SearchResult>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<MuclumbusService.SearchResult> call, Response<MuclumbusService.SearchResult> response) {
|
||||||
|
System.out.println(response.message());
|
||||||
|
MuclumbusService.SearchResult body = response.body();
|
||||||
|
if (body == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cache.put(query, body.result.items);
|
||||||
|
listener.onChannelSearchResultsFound(body.result.items);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<MuclumbusService.SearchResult> call, Throwable throwable) {
|
||||||
|
Log.d(Config.LOGTAG, "Unable to query muclumbus on "+Config.CHANNEL_DISCOVERY, throwable);
|
||||||
|
listener.onChannelSearchResultsFound(Collections.emptyList());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnChannelSearchResultsFound {
|
||||||
|
void onChannelSearchResultsFound(List<MuclumbusService.Room> results);
|
||||||
|
}
|
||||||
|
}
|
|
@ -192,7 +192,7 @@ public class ExportBackupService extends Service {
|
||||||
final String value = cursor.getString(i);
|
final String value = cursor.getString(i);
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
builder.append("NULL");
|
builder.append("NULL");
|
||||||
} else if (value.matches("\\d+")) {
|
} else if (value.matches("[0-9]+")) {
|
||||||
builder.append(value);
|
builder.append(value);
|
||||||
} else {
|
} else {
|
||||||
DatabaseUtils.appendEscapedSQLString(builder, value);
|
DatabaseUtils.appendEscapedSQLString(builder, value);
|
||||||
|
|
|
@ -868,7 +868,7 @@ public class NotificationService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final Matcher m = highlight.matcher(message.getBody());
|
final Matcher m = highlight.matcher(message.getBody());
|
||||||
return (m.find() || message.getType() == Message.TYPE_PRIVATE);
|
return (m.find() || message.isPrivateMessage());
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,6 +68,9 @@ import java.util.Set;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
@ -100,6 +103,7 @@ import eu.siacs.conversations.generator.MessageGenerator;
|
||||||
import eu.siacs.conversations.generator.PresenceGenerator;
|
import eu.siacs.conversations.generator.PresenceGenerator;
|
||||||
import eu.siacs.conversations.http.HttpConnectionManager;
|
import eu.siacs.conversations.http.HttpConnectionManager;
|
||||||
import eu.siacs.conversations.http.CustomURLStreamHandlerFactory;
|
import eu.siacs.conversations.http.CustomURLStreamHandlerFactory;
|
||||||
|
import eu.siacs.conversations.http.services.MuclumbusService;
|
||||||
import eu.siacs.conversations.parser.AbstractParser;
|
import eu.siacs.conversations.parser.AbstractParser;
|
||||||
import eu.siacs.conversations.parser.IqParser;
|
import eu.siacs.conversations.parser.IqParser;
|
||||||
import eu.siacs.conversations.parser.MessageParser;
|
import eu.siacs.conversations.parser.MessageParser;
|
||||||
|
@ -151,6 +155,11 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
|
||||||
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
|
||||||
import me.leolin.shortcutbadger.ShortcutBadger;
|
import me.leolin.shortcutbadger.ShortcutBadger;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
import retrofit2.Retrofit;
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory;
|
||||||
import rocks.xmpp.addr.Jid;
|
import rocks.xmpp.addr.Jid;
|
||||||
|
|
||||||
public class XmppConnectionService extends Service {
|
public class XmppConnectionService extends Service {
|
||||||
|
@ -200,6 +209,7 @@ public class XmppConnectionService extends Service {
|
||||||
private FileBackend fileBackend = new FileBackend(this);
|
private FileBackend fileBackend = new FileBackend(this);
|
||||||
private MemorizingTrustManager mMemorizingTrustManager;
|
private MemorizingTrustManager mMemorizingTrustManager;
|
||||||
private NotificationService mNotificationService = new NotificationService(this);
|
private NotificationService mNotificationService = new NotificationService(this);
|
||||||
|
private ChannelDiscoveryService mChannelDiscoveryService = new ChannelDiscoveryService(this);
|
||||||
private ShortcutService mShortcutService = new ShortcutService(this);
|
private ShortcutService mShortcutService = new ShortcutService(this);
|
||||||
private AtomicBoolean mInitialAddressbookSyncCompleted = new AtomicBoolean(false);
|
private AtomicBoolean mInitialAddressbookSyncCompleted = new AtomicBoolean(false);
|
||||||
private AtomicBoolean mForceForegroundService = new AtomicBoolean(false);
|
private AtomicBoolean mForceForegroundService = new AtomicBoolean(false);
|
||||||
|
@ -477,9 +487,7 @@ public class XmppConnectionService extends Service {
|
||||||
encryption = Message.ENCRYPTION_DECRYPTED;
|
encryption = Message.ENCRYPTION_DECRYPTED;
|
||||||
}
|
}
|
||||||
Message message = new Message(conversation, uri.toString(), encryption);
|
Message message = new Message(conversation, uri.toString(), encryption);
|
||||||
if (conversation.getNextCounterpart() != null) {
|
Message.configurePrivateMessage(message);
|
||||||
message.setCounterpart(conversation.getNextCounterpart());
|
|
||||||
}
|
|
||||||
if (encryption == Message.ENCRYPTION_DECRYPTED) {
|
if (encryption == Message.ENCRYPTION_DECRYPTED) {
|
||||||
getPgpEngine().encrypt(message, callback);
|
getPgpEngine().encrypt(message, callback);
|
||||||
} else {
|
} else {
|
||||||
|
@ -495,8 +503,12 @@ public class XmppConnectionService extends Service {
|
||||||
} else {
|
} else {
|
||||||
message = new Message(conversation, "", conversation.getNextEncryption());
|
message = new Message(conversation, "", conversation.getNextEncryption());
|
||||||
}
|
}
|
||||||
message.setCounterpart(conversation.getNextCounterpart());
|
if (!Message.configurePrivateFileMessage(message)) {
|
||||||
message.setType(Message.TYPE_FILE);
|
message.setCounterpart(conversation.getNextCounterpart());
|
||||||
|
message.setType(Message.TYPE_FILE);
|
||||||
|
}
|
||||||
|
Log.d(Config.LOGTAG,"attachFile: type="+message.getType());
|
||||||
|
Log.d(Config.LOGTAG,"counterpart="+message.getCounterpart());
|
||||||
final AttachFileToConversationRunnable runnable = new AttachFileToConversationRunnable(this, uri, type, message, callback);
|
final AttachFileToConversationRunnable runnable = new AttachFileToConversationRunnable(this, uri, type, message, callback);
|
||||||
if (runnable.isVideoMessage()) {
|
if (runnable.isVideoMessage()) {
|
||||||
mVideoCompressionExecutor.execute(runnable);
|
mVideoCompressionExecutor.execute(runnable);
|
||||||
|
@ -523,8 +535,11 @@ public class XmppConnectionService extends Service {
|
||||||
} else {
|
} else {
|
||||||
message = new Message(conversation, "", conversation.getNextEncryption());
|
message = new Message(conversation, "", conversation.getNextEncryption());
|
||||||
}
|
}
|
||||||
message.setCounterpart(conversation.getNextCounterpart());
|
if (!Message.configurePrivateFileMessage(message)) {
|
||||||
message.setType(Message.TYPE_IMAGE);
|
message.setCounterpart(conversation.getNextCounterpart());
|
||||||
|
message.setType(Message.TYPE_IMAGE);
|
||||||
|
}
|
||||||
|
Log.d(Config.LOGTAG,"attachImage: type="+message.getType());
|
||||||
mFileAddingExecutor.execute(() -> {
|
mFileAddingExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
getFileBackend().copyImageToPrivateStorage(message, uri);
|
getFileBackend().copyImageToPrivateStorage(message, uri);
|
||||||
|
@ -795,6 +810,14 @@ public class XmppConnectionService extends Service {
|
||||||
return pingNow;
|
return pingNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reinitializeMuclumbusService() {
|
||||||
|
mChannelDiscoveryService.initializeMuclumbusService();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void discoverChannels(String query, ChannelDiscoveryService.OnChannelSearchResultsFound onChannelSearchResultsFound) {
|
||||||
|
mChannelDiscoveryService.discover(query, onChannelSearchResultsFound);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isDataSaverDisabled() {
|
public boolean isDataSaverDisabled() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
|
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
|
||||||
|
@ -920,7 +943,7 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (account.setShowErrorNotification(true)) {
|
if (account.setShowErrorNotification(true)) {
|
||||||
databaseBackend.updateAccount(account);
|
mDatabaseWriterExecutor.execute(() -> databaseBackend.updateAccount(account));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mNotificationService.updateErrorNotification();
|
mNotificationService.updateErrorNotification();
|
||||||
|
@ -931,7 +954,7 @@ public class XmppConnectionService extends Service {
|
||||||
if (account.hasErrorStatus()) {
|
if (account.hasErrorStatus()) {
|
||||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": dismissing error notification");
|
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": dismissing error notification");
|
||||||
if (account.setShowErrorNotification(false)) {
|
if (account.setShowErrorNotification(false)) {
|
||||||
databaseBackend.updateAccount(account);
|
mDatabaseWriterExecutor.execute(() -> databaseBackend.updateAccount(account));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -978,6 +1001,7 @@ public class XmppConnectionService extends Service {
|
||||||
if (Compatibility.runsTwentySix()) {
|
if (Compatibility.runsTwentySix()) {
|
||||||
mNotificationService.initializeChannels();
|
mNotificationService.initializeChannels();
|
||||||
}
|
}
|
||||||
|
mChannelDiscoveryService.initializeMuclumbusService();
|
||||||
mForceDuringOnCreate.set(Compatibility.runsAndTargetsTwentySix(this));
|
mForceDuringOnCreate.set(Compatibility.runsAndTargetsTwentySix(this));
|
||||||
toggleForegroundService();
|
toggleForegroundService();
|
||||||
this.destroyed = false;
|
this.destroyed = false;
|
||||||
|
@ -1412,7 +1436,7 @@ public class XmppConnectionService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boolean mucMessage = conversation.getMode() == Conversation.MODE_MULTI && message.getType() != Message.TYPE_PRIVATE;
|
boolean mucMessage = conversation.getMode() == Conversation.MODE_MULTI && !message.isPrivateMessage();
|
||||||
if (mucMessage) {
|
if (mucMessage) {
|
||||||
message.setCounterpart(conversation.getMucOptions().getSelf().getFullJid());
|
message.setCounterpart(conversation.getMucOptions().getSelf().getFullJid());
|
||||||
}
|
}
|
||||||
|
@ -1447,6 +1471,7 @@ public class XmppConnectionService extends Service {
|
||||||
packet.addChild(ChatState.toElement(conversation.getOutgoingChatState()));
|
packet.addChild(ChatState.toElement(conversation.getOutgoingChatState()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Log.d(Config.LOGTAG,packet.toString());
|
||||||
sendMessagePacket(account, packet);
|
sendMessagePacket(account, packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,8 @@ public class BlocklistActivity extends AbstractSearchableListItemActivity implem
|
||||||
getString(R.string.block),
|
getString(R.string.block),
|
||||||
null,
|
null,
|
||||||
account.getJid().asBareJid().toString(),
|
account.getJid().asBareJid().toString(),
|
||||||
true
|
true,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
dialog.setOnEnterJidDialogPositiveListener((accountJid, contactJid) -> {
|
dialog.setOnEnterJidDialogPositiveListener((accountJid, contactJid) -> {
|
||||||
|
|
|
@ -0,0 +1,218 @@
|
||||||
|
package eu.siacs.conversations.ui;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.databinding.DataBindingUtil;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.text.Html;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.inputmethod.InputMethodManager;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.R;
|
||||||
|
import eu.siacs.conversations.databinding.ActivityChannelDiscoveryBinding;
|
||||||
|
import eu.siacs.conversations.entities.Account;
|
||||||
|
import eu.siacs.conversations.entities.Bookmark;
|
||||||
|
import eu.siacs.conversations.entities.Conversation;
|
||||||
|
import eu.siacs.conversations.http.services.MuclumbusService;
|
||||||
|
import eu.siacs.conversations.services.ChannelDiscoveryService;
|
||||||
|
import eu.siacs.conversations.ui.adapter.ChannelSearchResultAdapter;
|
||||||
|
import eu.siacs.conversations.ui.util.PendingItem;
|
||||||
|
import eu.siacs.conversations.ui.util.SoftKeyboardUtils;
|
||||||
|
import eu.siacs.conversations.utils.AccountUtils;
|
||||||
|
import rocks.xmpp.addr.Jid;
|
||||||
|
|
||||||
|
public class ChannelDiscoveryActivity extends XmppActivity implements MenuItem.OnActionExpandListener, TextView.OnEditorActionListener, ChannelDiscoveryService.OnChannelSearchResultsFound, ChannelSearchResultAdapter.OnChannelSearchResultSelected {
|
||||||
|
|
||||||
|
private static final String CHANNEL_DISCOVERY_OPT_IN = "channel_discovery_opt_in";
|
||||||
|
|
||||||
|
private final ChannelSearchResultAdapter adapter = new ChannelSearchResultAdapter();
|
||||||
|
|
||||||
|
private ActivityChannelDiscoveryBinding binding;
|
||||||
|
|
||||||
|
private final PendingItem<String> mInitialSearchValue = new PendingItem<>();
|
||||||
|
|
||||||
|
private MenuItem mMenuSearchView;
|
||||||
|
private EditText mSearchEditText;
|
||||||
|
|
||||||
|
private boolean optedIn = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refreshUiReal() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onBackendConnected() {
|
||||||
|
if (optedIn) {
|
||||||
|
String query;
|
||||||
|
if (mMenuSearchView != null && mMenuSearchView.isActionViewExpanded()) {
|
||||||
|
query = mSearchEditText.getText().toString();
|
||||||
|
} else {
|
||||||
|
query = mInitialSearchValue.peek();
|
||||||
|
}
|
||||||
|
xmppConnectionService.discoverChannels(query, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(final Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
binding = DataBindingUtil.setContentView(this, R.layout.activity_channel_discovery);
|
||||||
|
setSupportActionBar((Toolbar) binding.toolbar);
|
||||||
|
configureActionBar(getSupportActionBar(), true);
|
||||||
|
binding.list.setAdapter(this.adapter);
|
||||||
|
this.adapter.setOnChannelSearchResultSelectedListener(this);
|
||||||
|
optedIn = getPreferences().getBoolean(CHANNEL_DISCOVERY_OPT_IN, false);
|
||||||
|
|
||||||
|
final String search = savedInstanceState == null ? null : savedInstanceState.getString("search");
|
||||||
|
if (search != null) {
|
||||||
|
mInitialSearchValue.push(search);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||||
|
getMenuInflater().inflate(R.menu.muc_users_activity, menu);
|
||||||
|
mMenuSearchView = menu.findItem(R.id.action_search);
|
||||||
|
final View mSearchView = mMenuSearchView.getActionView();
|
||||||
|
mSearchEditText = mSearchView.findViewById(R.id.search_field);
|
||||||
|
mSearchEditText.setHint(R.string.search_channels);
|
||||||
|
String initialSearchValue = mInitialSearchValue.pop();
|
||||||
|
if (initialSearchValue != null) {
|
||||||
|
mMenuSearchView.expandActionView();
|
||||||
|
mSearchEditText.append(initialSearchValue);
|
||||||
|
mSearchEditText.requestFocus();
|
||||||
|
if (optedIn) {
|
||||||
|
xmppConnectionService.discoverChannels(initialSearchValue, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mSearchEditText.setOnEditorActionListener(this);
|
||||||
|
mMenuSearchView.setOnActionExpandListener(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemActionExpand(MenuItem item) {
|
||||||
|
mSearchEditText.post(() -> {
|
||||||
|
mSearchEditText.requestFocus();
|
||||||
|
final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
imm.showSoftInput(mSearchEditText, InputMethodManager.SHOW_IMPLICIT);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemActionCollapse(MenuItem item) {
|
||||||
|
final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||||
|
imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
|
||||||
|
mSearchEditText.setText("");
|
||||||
|
toggleLoadingScreen();
|
||||||
|
if (optedIn) {
|
||||||
|
xmppConnectionService.discoverChannels(null, this);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void toggleLoadingScreen() {
|
||||||
|
adapter.submitList(Collections.emptyList());
|
||||||
|
binding.progressBar.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
if (!optedIn) {
|
||||||
|
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setTitle(R.string.channel_discovery_opt_in_title);
|
||||||
|
builder.setMessage(Html.fromHtml(getString(R.string.channel_discover_opt_in_message)));
|
||||||
|
builder.setNegativeButton(R.string.cancel, (dialog, which) -> finish());
|
||||||
|
builder.setPositiveButton(R.string.confirm, (dialog, which) -> optIn());
|
||||||
|
builder.setOnCancelListener(dialog -> finish());
|
||||||
|
final AlertDialog dialog = builder.create();
|
||||||
|
dialog.setCanceledOnTouchOutside(false);
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSaveInstanceState(Bundle savedInstanceState) {
|
||||||
|
if (mMenuSearchView != null && mMenuSearchView.isActionViewExpanded()) {
|
||||||
|
savedInstanceState.putString("search", mSearchEditText != null ? mSearchEditText.getText().toString() : null);
|
||||||
|
}
|
||||||
|
super.onSaveInstanceState(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void optIn() {
|
||||||
|
SharedPreferences preferences = getPreferences();
|
||||||
|
preferences.edit().putBoolean(CHANNEL_DISCOVERY_OPT_IN, true).apply();
|
||||||
|
optedIn = true;
|
||||||
|
xmppConnectionService.discoverChannels(null, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||||
|
if (optedIn) {
|
||||||
|
xmppConnectionService.discoverChannels(v.getText().toString(), this);
|
||||||
|
}
|
||||||
|
toggleLoadingScreen();
|
||||||
|
SoftKeyboardUtils.hideSoftKeyboard(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChannelSearchResultsFound(List<MuclumbusService.Room> results) {
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
adapter.submitList(results);
|
||||||
|
binding.list.setVisibility(View.VISIBLE);
|
||||||
|
binding.progressBar.setVisibility(View.GONE);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onChannelSearchResult(final MuclumbusService.Room result) {
|
||||||
|
List<String> accounts = AccountUtils.getEnabledAccounts(xmppConnectionService);
|
||||||
|
if (accounts.size() == 1) {
|
||||||
|
joinChannelSearchResult(accounts.get(0), result);
|
||||||
|
} else if (accounts.size() > 0) {
|
||||||
|
final AtomicReference<String> account = new AtomicReference<>(accounts.get(0));
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setTitle(R.string.choose_account);
|
||||||
|
builder.setSingleChoiceItems(accounts.toArray(new CharSequence[0]), 0, (dialog, which) -> account.set(accounts.get(which)));
|
||||||
|
builder.setPositiveButton(R.string.join, (dialog, which) -> joinChannelSearchResult(account.get(), result));
|
||||||
|
builder.setNegativeButton(R.string.cancel, null);
|
||||||
|
builder.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void joinChannelSearchResult(String accountJid, MuclumbusService.Room result) {
|
||||||
|
final boolean syncAutojoin = getBooleanPreference("autojoin", R.bool.autojoin);
|
||||||
|
Account account = xmppConnectionService.findAccountByJid(Jid.of(accountJid));
|
||||||
|
final Conversation conversation = xmppConnectionService.findOrCreateConversation(account, result.getRoom(), true, true, true);
|
||||||
|
if (conversation.getBookmark() != null) {
|
||||||
|
if (!conversation.getBookmark().autojoin() && syncAutojoin) {
|
||||||
|
conversation.getBookmark().setAutojoin(true);
|
||||||
|
xmppConnectionService.pushBookmarks(account);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final Bookmark bookmark = new Bookmark(account, conversation.getJid().asBareJid());
|
||||||
|
bookmark.setAutojoin(syncAutojoin);
|
||||||
|
account.getBookmarks().add(bookmark);
|
||||||
|
xmppConnectionService.pushBookmarks(account);
|
||||||
|
}
|
||||||
|
switchToConversation(conversation);
|
||||||
|
}
|
||||||
|
}
|
|
@ -313,7 +313,8 @@ public class ChooseContactActivity extends AbstractSearchableListItemActivity im
|
||||||
getString(R.string.select),
|
getString(R.string.select),
|
||||||
jid == null ? null : jid.asBareJid().toString(),
|
jid == null ? null : jid.asBareJid().toString(),
|
||||||
getIntent().getStringExtra(EXTRA_ACCOUNT),
|
getIntent().getStringExtra(EXTRA_ACCOUNT),
|
||||||
true
|
true,
|
||||||
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
dialog.setOnEnterJidDialogPositiveListener((accountJid, contactJid) -> {
|
dialog.setOnEnterJidDialogPositiveListener((accountJid, contactJid) -> {
|
||||||
|
|
|
@ -432,6 +432,9 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
conversation.setDraftMessage(null);
|
conversation.setDraftMessage(null);
|
||||||
} else if (conversation.getMode() == Conversation.MODE_MULTI) {
|
} else if (conversation.getMode() == Conversation.MODE_MULTI) {
|
||||||
conversation.setNextCounterpart(null);
|
conversation.setNextCounterpart(null);
|
||||||
|
binding.textinput.setText("");
|
||||||
|
} else {
|
||||||
|
binding.textinput.setText("");
|
||||||
}
|
}
|
||||||
updateChatMsgHint();
|
updateChatMsgHint();
|
||||||
updateSendButton();
|
updateSendButton();
|
||||||
|
@ -455,11 +458,11 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
|
|
||||||
private static ConversationFragment findConversationFragment(Activity activity) {
|
private static ConversationFragment findConversationFragment(Activity activity) {
|
||||||
Fragment fragment = activity.getFragmentManager().findFragmentById(R.id.main_fragment);
|
Fragment fragment = activity.getFragmentManager().findFragmentById(R.id.main_fragment);
|
||||||
if (fragment != null && fragment instanceof ConversationFragment) {
|
if (fragment instanceof ConversationFragment) {
|
||||||
return (ConversationFragment) fragment;
|
return (ConversationFragment) fragment;
|
||||||
}
|
}
|
||||||
fragment = activity.getFragmentManager().findFragmentById(R.id.secondary_fragment);
|
fragment = activity.getFragmentManager().findFragmentById(R.id.secondary_fragment);
|
||||||
if (fragment != null && fragment instanceof ConversationFragment) {
|
if (fragment instanceof ConversationFragment) {
|
||||||
return (ConversationFragment) fragment;
|
return (ConversationFragment) fragment;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -725,14 +728,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
final Message message;
|
final Message message;
|
||||||
if (conversation.getCorrectingMessage() == null) {
|
if (conversation.getCorrectingMessage() == null) {
|
||||||
message = new Message(conversation, body, conversation.getNextEncryption());
|
message = new Message(conversation, body, conversation.getNextEncryption());
|
||||||
if (conversation.getMode() == Conversation.MODE_MULTI) {
|
Message.configurePrivateMessage(message);
|
||||||
final Jid nextCounterpart = conversation.getNextCounterpart();
|
|
||||||
if (nextCounterpart != null) {
|
|
||||||
message.setCounterpart(nextCounterpart);
|
|
||||||
message.setTrueCounterpart(conversation.getMucOptions().getTrueCounterpart(nextCounterpart));
|
|
||||||
message.setType(Message.TYPE_PRIVATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
message = conversation.getCorrectingMessage();
|
message = conversation.getCorrectingMessage();
|
||||||
message.setBody(body);
|
message.setBody(body);
|
||||||
|
@ -778,14 +774,19 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
public void updateChatMsgHint() {
|
public void updateChatMsgHint() {
|
||||||
final boolean multi = conversation.getMode() == Conversation.MODE_MULTI;
|
final boolean multi = conversation.getMode() == Conversation.MODE_MULTI;
|
||||||
if (conversation.getCorrectingMessage() != null) {
|
if (conversation.getCorrectingMessage() != null) {
|
||||||
|
this.binding.textInputHint.setVisibility(View.GONE);
|
||||||
this.binding.textinput.setHint(R.string.send_corrected_message);
|
this.binding.textinput.setHint(R.string.send_corrected_message);
|
||||||
} else if (multi && conversation.getNextCounterpart() != null) {
|
} else if (multi && conversation.getNextCounterpart() != null) {
|
||||||
this.binding.textinput.setHint(getString(
|
this.binding.textinput.setHint(R.string.send_unencrypted_message);
|
||||||
|
this.binding.textInputHint.setVisibility(View.VISIBLE);
|
||||||
|
this.binding.textInputHint.setText(getString(
|
||||||
R.string.send_private_message_to,
|
R.string.send_private_message_to,
|
||||||
conversation.getNextCounterpart().getResource()));
|
conversation.getNextCounterpart().getResource()));
|
||||||
} else if (multi && !conversation.getMucOptions().participating()) {
|
} else if (multi && !conversation.getMucOptions().participating()) {
|
||||||
|
this.binding.textInputHint.setVisibility(View.GONE);
|
||||||
this.binding.textinput.setHint(R.string.you_are_not_participating);
|
this.binding.textinput.setHint(R.string.you_are_not_participating);
|
||||||
} else {
|
} else {
|
||||||
|
this.binding.textInputHint.setVisibility(View.GONE);
|
||||||
this.binding.textinput.setHint(UIHelper.getMessageHint(getActivity(), conversation));
|
this.binding.textinput.setHint(UIHelper.getMessageHint(getActivity(), conversation));
|
||||||
getActivity().invalidateOptionsMenu();
|
getActivity().invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
@ -876,7 +877,10 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
mediaPreviewAdapter.notifyDataSetChanged();
|
mediaPreviewAdapter.notifyDataSetChanged();
|
||||||
toggleInputMethod();
|
toggleInputMethod();
|
||||||
};
|
};
|
||||||
if (conversation == null || conversation.getMode() == Conversation.MODE_MULTI || FileBackend.allFilesUnderSize(getActivity(), attachments, getMaxHttpUploadSize(conversation))) {
|
if (conversation == null
|
||||||
|
|| conversation.getMode() == Conversation.MODE_MULTI
|
||||||
|
|| Attachment.canBeSendInband(attachments)
|
||||||
|
|| (conversation.getAccount().httpUploadAvailable() && FileBackend.allFilesUnderSize(getActivity(), attachments, getMaxHttpUploadSize(conversation)))) {
|
||||||
callback.onPresenceSelected();
|
callback.onPresenceSelected();
|
||||||
} else {
|
} else {
|
||||||
activity.selectPresence(conversation, callback);
|
activity.selectPresence(conversation, callback);
|
||||||
|
@ -1328,7 +1332,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void success(Contact contact) {
|
public void success(Contact contact) {
|
||||||
selectPresenceToAttachFile(attachmentChoice);
|
invokeAttachFileIntent(attachmentChoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1342,19 +1346,19 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
warning.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
|
warning.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
|
||||||
warning.show();
|
warning.show();
|
||||||
}
|
}
|
||||||
selectPresenceToAttachFile(attachmentChoice);
|
invokeAttachFileIntent(attachmentChoice);
|
||||||
} else {
|
} else {
|
||||||
showNoPGPKeyDialog(false, (dialog, which) -> {
|
showNoPGPKeyDialog(false, (dialog, which) -> {
|
||||||
conversation.setNextEncryption(Message.ENCRYPTION_NONE);
|
conversation.setNextEncryption(Message.ENCRYPTION_NONE);
|
||||||
activity.xmppConnectionService.updateConversation(conversation);
|
activity.xmppConnectionService.updateConversation(conversation);
|
||||||
selectPresenceToAttachFile(attachmentChoice);
|
invokeAttachFileIntent(attachmentChoice);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
activity.showInstallPgpDialog();
|
activity.showInstallPgpDialog();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
selectPresenceToAttachFile(attachmentChoice);
|
invokeAttachFileIntent(attachmentChoice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1508,62 +1512,54 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
getActivity().invalidateOptionsMenu();
|
getActivity().invalidateOptionsMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void selectPresenceToAttachFile(final int attachmentChoice) {
|
|
||||||
final Account account = conversation.getAccount();
|
protected void invokeAttachFileIntent(final int attachmentChoice) {
|
||||||
final PresenceSelector.OnPresenceSelected callback = () -> {
|
Intent intent = new Intent();
|
||||||
Intent intent = new Intent();
|
boolean chooser = false;
|
||||||
boolean chooser = false;
|
switch (attachmentChoice) {
|
||||||
switch (attachmentChoice) {
|
case ATTACHMENT_CHOICE_CHOOSE_IMAGE:
|
||||||
case ATTACHMENT_CHOICE_CHOOSE_IMAGE:
|
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
|
||||||
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
|
|
||||||
}
|
|
||||||
intent.setType("image/*");
|
|
||||||
chooser = true;
|
|
||||||
break;
|
|
||||||
case ATTACHMENT_CHOICE_RECORD_VIDEO:
|
|
||||||
intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE);
|
|
||||||
break;
|
|
||||||
case ATTACHMENT_CHOICE_TAKE_PHOTO:
|
|
||||||
final Uri uri = activity.xmppConnectionService.getFileBackend().getTakePhotoUri();
|
|
||||||
pendingTakePhotoUri.push(uri);
|
|
||||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
|
|
||||||
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
||||||
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
|
|
||||||
break;
|
|
||||||
case ATTACHMENT_CHOICE_CHOOSE_FILE:
|
|
||||||
chooser = true;
|
|
||||||
intent.setType("*/*");
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
|
||||||
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
|
|
||||||
}
|
|
||||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
|
||||||
intent.setAction(Intent.ACTION_GET_CONTENT);
|
|
||||||
break;
|
|
||||||
case ATTACHMENT_CHOICE_RECORD_VOICE:
|
|
||||||
intent = new Intent(getActivity(), RecordingActivity.class);
|
|
||||||
break;
|
|
||||||
case ATTACHMENT_CHOICE_LOCATION:
|
|
||||||
intent = GeoHelper.getFetchIntent(activity);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
|
|
||||||
if (chooser) {
|
|
||||||
startActivityForResult(
|
|
||||||
Intent.createChooser(intent, getString(R.string.perform_action_with)),
|
|
||||||
attachmentChoice);
|
|
||||||
} else {
|
|
||||||
startActivityForResult(intent, attachmentChoice);
|
|
||||||
}
|
}
|
||||||
|
intent.setType("image/*");
|
||||||
|
chooser = true;
|
||||||
|
break;
|
||||||
|
case ATTACHMENT_CHOICE_RECORD_VIDEO:
|
||||||
|
intent.setAction(MediaStore.ACTION_VIDEO_CAPTURE);
|
||||||
|
break;
|
||||||
|
case ATTACHMENT_CHOICE_TAKE_PHOTO:
|
||||||
|
final Uri uri = activity.xmppConnectionService.getFileBackend().getTakePhotoUri();
|
||||||
|
pendingTakePhotoUri.push(uri);
|
||||||
|
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||||
|
break;
|
||||||
|
case ATTACHMENT_CHOICE_CHOOSE_FILE:
|
||||||
|
chooser = true;
|
||||||
|
intent.setType("*/*");
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||||
|
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
|
||||||
|
}
|
||||||
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
|
intent.setAction(Intent.ACTION_GET_CONTENT);
|
||||||
|
break;
|
||||||
|
case ATTACHMENT_CHOICE_RECORD_VOICE:
|
||||||
|
intent = new Intent(getActivity(), RecordingActivity.class);
|
||||||
|
break;
|
||||||
|
case ATTACHMENT_CHOICE_LOCATION:
|
||||||
|
intent = GeoHelper.getFetchIntent(activity);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
|
||||||
|
if (chooser) {
|
||||||
|
startActivityForResult(
|
||||||
|
Intent.createChooser(intent, getString(R.string.perform_action_with)),
|
||||||
|
attachmentChoice);
|
||||||
|
} else {
|
||||||
|
startActivityForResult(intent, attachmentChoice);
|
||||||
}
|
}
|
||||||
};
|
|
||||||
if (account.httpUploadAvailable() || attachmentChoice == ATTACHMENT_CHOICE_LOCATION) {
|
|
||||||
conversation.setNextCounterpart(null);
|
|
||||||
callback.onPresenceSelected();
|
|
||||||
} else {
|
|
||||||
activity.selectPresence(conversation, callback);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2283,110 +2279,102 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
this.binding.textSendButton.setImageResource(SendButtonTool.getSendButtonImageResource(getActivity(), action, status));
|
this.binding.textSendButton.setImageResource(SendButtonTool.getSendButtonImageResource(getActivity(), action, status));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void updateDateSeparators() {
|
|
||||||
synchronized (this.messageList) {
|
|
||||||
DateSeparator.addAll(this.messageList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void updateStatusMessages() {
|
protected void updateStatusMessages() {
|
||||||
updateDateSeparators();
|
DateSeparator.addAll(this.messageList);
|
||||||
synchronized (this.messageList) {
|
if (showLoadMoreMessages(conversation)) {
|
||||||
if (showLoadMoreMessages(conversation)) {
|
this.messageList.add(0, Message.createLoadMoreMessage(conversation));
|
||||||
this.messageList.add(0, Message.createLoadMoreMessage(conversation));
|
}
|
||||||
}
|
if (conversation.getMode() == Conversation.MODE_SINGLE) {
|
||||||
if (conversation.getMode() == Conversation.MODE_SINGLE) {
|
ChatState state = conversation.getIncomingChatState();
|
||||||
ChatState state = conversation.getIncomingChatState();
|
if (state == ChatState.COMPOSING) {
|
||||||
if (state == ChatState.COMPOSING) {
|
this.messageList.add(Message.createStatusMessage(conversation, getString(R.string.contact_is_typing, conversation.getName())));
|
||||||
this.messageList.add(Message.createStatusMessage(conversation, getString(R.string.contact_is_typing, conversation.getName())));
|
} else if (state == ChatState.PAUSED) {
|
||||||
} else if (state == ChatState.PAUSED) {
|
this.messageList.add(Message.createStatusMessage(conversation, getString(R.string.contact_has_stopped_typing, conversation.getName())));
|
||||||
this.messageList.add(Message.createStatusMessage(conversation, getString(R.string.contact_has_stopped_typing, conversation.getName())));
|
|
||||||
} else {
|
|
||||||
for (int i = this.messageList.size() - 1; i >= 0; --i) {
|
|
||||||
final Message message = this.messageList.get(i);
|
|
||||||
if (message.getType() != Message.TYPE_STATUS) {
|
|
||||||
if (message.getStatus() == Message.STATUS_RECEIVED) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
if (message.getStatus() == Message.STATUS_SEND_DISPLAYED) {
|
|
||||||
this.messageList.add(i + 1,
|
|
||||||
Message.createStatusMessage(conversation, getString(R.string.contact_has_read_up_to_this_point, conversation.getName())));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
final MucOptions mucOptions = conversation.getMucOptions();
|
for (int i = this.messageList.size() - 1; i >= 0; --i) {
|
||||||
final List<MucOptions.User> allUsers = mucOptions.getUsers();
|
final Message message = this.messageList.get(i);
|
||||||
final Set<ReadByMarker> addedMarkers = new HashSet<>();
|
if (message.getType() != Message.TYPE_STATUS) {
|
||||||
ChatState state = ChatState.COMPOSING;
|
if (message.getStatus() == Message.STATUS_RECEIVED) {
|
||||||
List<MucOptions.User> users = conversation.getMucOptions().getUsersWithChatState(state, 5);
|
return;
|
||||||
if (users.size() == 0) {
|
|
||||||
state = ChatState.PAUSED;
|
|
||||||
users = conversation.getMucOptions().getUsersWithChatState(state, 5);
|
|
||||||
}
|
|
||||||
if (mucOptions.isPrivateAndNonAnonymous()) {
|
|
||||||
for (int i = this.messageList.size() - 1; i >= 0; --i) {
|
|
||||||
final Set<ReadByMarker> markersForMessage = messageList.get(i).getReadByMarkers();
|
|
||||||
final List<MucOptions.User> shownMarkers = new ArrayList<>();
|
|
||||||
for (ReadByMarker marker : markersForMessage) {
|
|
||||||
if (!ReadByMarker.contains(marker, addedMarkers)) {
|
|
||||||
addedMarkers.add(marker); //may be put outside this condition. set should do dedup anyway
|
|
||||||
MucOptions.User user = mucOptions.findUser(marker);
|
|
||||||
if (user != null && !users.contains(user)) {
|
|
||||||
shownMarkers.add(user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final ReadByMarker markerForSender = ReadByMarker.from(messageList.get(i));
|
|
||||||
final Message statusMessage;
|
|
||||||
final int size = shownMarkers.size();
|
|
||||||
if (size > 1) {
|
|
||||||
final String body;
|
|
||||||
if (size <= 4) {
|
|
||||||
body = getString(R.string.contacts_have_read_up_to_this_point, UIHelper.concatNames(shownMarkers));
|
|
||||||
} else if (ReadByMarker.allUsersRepresented(allUsers, markersForMessage, markerForSender)) {
|
|
||||||
body = getString(R.string.everyone_has_read_up_to_this_point);
|
|
||||||
} else {
|
|
||||||
body = getString(R.string.contacts_and_n_more_have_read_up_to_this_point, UIHelper.concatNames(shownMarkers, 3), size - 3);
|
|
||||||
}
|
|
||||||
statusMessage = Message.createStatusMessage(conversation, body);
|
|
||||||
statusMessage.setCounterparts(shownMarkers);
|
|
||||||
} else if (size == 1) {
|
|
||||||
statusMessage = Message.createStatusMessage(conversation, getString(R.string.contact_has_read_up_to_this_point, UIHelper.getDisplayName(shownMarkers.get(0))));
|
|
||||||
statusMessage.setCounterpart(shownMarkers.get(0).getFullJid());
|
|
||||||
statusMessage.setTrueCounterpart(shownMarkers.get(0).getRealJid());
|
|
||||||
} else {
|
} else {
|
||||||
statusMessage = null;
|
if (message.getStatus() == Message.STATUS_SEND_DISPLAYED) {
|
||||||
}
|
this.messageList.add(i + 1,
|
||||||
if (statusMessage != null) {
|
Message.createStatusMessage(conversation, getString(R.string.contact_has_read_up_to_this_point, conversation.getName())));
|
||||||
this.messageList.add(i + 1, statusMessage);
|
return;
|
||||||
}
|
}
|
||||||
addedMarkers.add(markerForSender);
|
|
||||||
if (ReadByMarker.allUsersRepresented(allUsers, addedMarkers)) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (users.size() > 0) {
|
|
||||||
Message statusMessage;
|
|
||||||
if (users.size() == 1) {
|
|
||||||
MucOptions.User user = users.get(0);
|
|
||||||
int id = state == ChatState.COMPOSING ? R.string.contact_is_typing : R.string.contact_has_stopped_typing;
|
|
||||||
statusMessage = Message.createStatusMessage(conversation, getString(id, UIHelper.getDisplayName(user)));
|
|
||||||
statusMessage.setTrueCounterpart(user.getRealJid());
|
|
||||||
statusMessage.setCounterpart(user.getFullJid());
|
|
||||||
} else {
|
|
||||||
int id = state == ChatState.COMPOSING ? R.string.contacts_are_typing : R.string.contacts_have_stopped_typing;
|
|
||||||
statusMessage = Message.createStatusMessage(conversation, getString(id, UIHelper.concatNames(users)));
|
|
||||||
statusMessage.setCounterparts(users);
|
|
||||||
}
|
|
||||||
this.messageList.add(statusMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
final MucOptions mucOptions = conversation.getMucOptions();
|
||||||
|
final List<MucOptions.User> allUsers = mucOptions.getUsers();
|
||||||
|
final Set<ReadByMarker> addedMarkers = new HashSet<>();
|
||||||
|
ChatState state = ChatState.COMPOSING;
|
||||||
|
List<MucOptions.User> users = conversation.getMucOptions().getUsersWithChatState(state, 5);
|
||||||
|
if (users.size() == 0) {
|
||||||
|
state = ChatState.PAUSED;
|
||||||
|
users = conversation.getMucOptions().getUsersWithChatState(state, 5);
|
||||||
|
}
|
||||||
|
if (mucOptions.isPrivateAndNonAnonymous()) {
|
||||||
|
for (int i = this.messageList.size() - 1; i >= 0; --i) {
|
||||||
|
final Set<ReadByMarker> markersForMessage = messageList.get(i).getReadByMarkers();
|
||||||
|
final List<MucOptions.User> shownMarkers = new ArrayList<>();
|
||||||
|
for (ReadByMarker marker : markersForMessage) {
|
||||||
|
if (!ReadByMarker.contains(marker, addedMarkers)) {
|
||||||
|
addedMarkers.add(marker); //may be put outside this condition. set should do dedup anyway
|
||||||
|
MucOptions.User user = mucOptions.findUser(marker);
|
||||||
|
if (user != null && !users.contains(user)) {
|
||||||
|
shownMarkers.add(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final ReadByMarker markerForSender = ReadByMarker.from(messageList.get(i));
|
||||||
|
final Message statusMessage;
|
||||||
|
final int size = shownMarkers.size();
|
||||||
|
if (size > 1) {
|
||||||
|
final String body;
|
||||||
|
if (size <= 4) {
|
||||||
|
body = getString(R.string.contacts_have_read_up_to_this_point, UIHelper.concatNames(shownMarkers));
|
||||||
|
} else if (ReadByMarker.allUsersRepresented(allUsers, markersForMessage, markerForSender)) {
|
||||||
|
body = getString(R.string.everyone_has_read_up_to_this_point);
|
||||||
|
} else {
|
||||||
|
body = getString(R.string.contacts_and_n_more_have_read_up_to_this_point, UIHelper.concatNames(shownMarkers, 3), size - 3);
|
||||||
|
}
|
||||||
|
statusMessage = Message.createStatusMessage(conversation, body);
|
||||||
|
statusMessage.setCounterparts(shownMarkers);
|
||||||
|
} else if (size == 1) {
|
||||||
|
statusMessage = Message.createStatusMessage(conversation, getString(R.string.contact_has_read_up_to_this_point, UIHelper.getDisplayName(shownMarkers.get(0))));
|
||||||
|
statusMessage.setCounterpart(shownMarkers.get(0).getFullJid());
|
||||||
|
statusMessage.setTrueCounterpart(shownMarkers.get(0).getRealJid());
|
||||||
|
} else {
|
||||||
|
statusMessage = null;
|
||||||
|
}
|
||||||
|
if (statusMessage != null) {
|
||||||
|
this.messageList.add(i + 1, statusMessage);
|
||||||
|
}
|
||||||
|
addedMarkers.add(markerForSender);
|
||||||
|
if (ReadByMarker.allUsersRepresented(allUsers, addedMarkers)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (users.size() > 0) {
|
||||||
|
Message statusMessage;
|
||||||
|
if (users.size() == 1) {
|
||||||
|
MucOptions.User user = users.get(0);
|
||||||
|
int id = state == ChatState.COMPOSING ? R.string.contact_is_typing : R.string.contact_has_stopped_typing;
|
||||||
|
statusMessage = Message.createStatusMessage(conversation, getString(id, UIHelper.getDisplayName(user)));
|
||||||
|
statusMessage.setTrueCounterpart(user.getRealJid());
|
||||||
|
statusMessage.setCounterpart(user.getFullJid());
|
||||||
|
} else {
|
||||||
|
int id = state == ChatState.COMPOSING ? R.string.contacts_are_typing : R.string.contacts_have_stopped_typing;
|
||||||
|
statusMessage = Message.createStatusMessage(conversation, getString(id, UIHelper.concatNames(users)));
|
||||||
|
statusMessage.setCounterparts(users);
|
||||||
|
}
|
||||||
|
this.messageList.add(statusMessage);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2592,7 +2580,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
if (status == Account.State.ONLINE && conversation.setOutgoingChatState(ChatState.COMPOSING)) {
|
if (status == Account.State.ONLINE && conversation.setOutgoingChatState(ChatState.COMPOSING)) {
|
||||||
service.sendChatState(conversation);
|
service.sendChatState(conversation);
|
||||||
}
|
}
|
||||||
updateSendButton();
|
runOnUiThread(this::updateSendButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2618,15 +2606,15 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
|
||||||
service.sendChatState(conversation);
|
service.sendChatState(conversation);
|
||||||
}
|
}
|
||||||
if (storeNextMessage()) {
|
if (storeNextMessage()) {
|
||||||
activity.onConversationsListItemUpdated();
|
runOnUiThread(() -> activity.onConversationsListItemUpdated());
|
||||||
}
|
}
|
||||||
updateSendButton();
|
runOnUiThread(this::updateSendButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTextChanged() {
|
public void onTextChanged() {
|
||||||
if (conversation != null && conversation.getCorrectingMessage() != null) {
|
if (conversation != null && conversation.getCorrectingMessage() != null) {
|
||||||
updateSendButton();
|
runOnUiThread(this::updateSendButton);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
||||||
OnKeyStatusUpdated, OnCaptchaRequested, KeyChainAliasCallback, XmppConnectionService.OnShowErrorToast, XmppConnectionService.OnMamPreferencesFetched {
|
OnKeyStatusUpdated, OnCaptchaRequested, KeyChainAliasCallback, XmppConnectionService.OnShowErrorToast, XmppConnectionService.OnMamPreferencesFetched {
|
||||||
|
|
||||||
public static final String EXTRA_OPENED_FROM_NOTIFICATION = "opened_from_notification";
|
public static final String EXTRA_OPENED_FROM_NOTIFICATION = "opened_from_notification";
|
||||||
|
public static final String EXTRA_FORCE_REGISTER = "force_register";
|
||||||
|
|
||||||
private static final int REQUEST_DATA_SAVER = 0xf244;
|
private static final int REQUEST_DATA_SAVER = 0xf244;
|
||||||
private static final int REQUEST_CHANGE_STATUS = 0xee11;
|
private static final int REQUEST_CHANGE_STATUS = 0xee11;
|
||||||
|
@ -92,6 +93,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
||||||
private AlertDialog mCaptchaDialog = null;
|
private AlertDialog mCaptchaDialog = null;
|
||||||
private Jid jidToEdit;
|
private Jid jidToEdit;
|
||||||
private boolean mInitMode = false;
|
private boolean mInitMode = false;
|
||||||
|
private Boolean mForceRegister = null;
|
||||||
private boolean mUsernameMode = Config.DOMAIN_LOCK != null;
|
private boolean mUsernameMode = Config.DOMAIN_LOCK != null;
|
||||||
private boolean mShowOptions = false;
|
private boolean mShowOptions = false;
|
||||||
private Account mAccount;
|
private Account mAccount;
|
||||||
|
@ -152,7 +154,12 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final boolean registerNewAccount = binding.accountRegisterNew.isChecked() && !Config.DISALLOW_REGISTRATION_IN_UI;
|
final boolean registerNewAccount;
|
||||||
|
if (mForceRegister != null) {
|
||||||
|
registerNewAccount = mForceRegister;
|
||||||
|
} else {
|
||||||
|
registerNewAccount = binding.accountRegisterNew.isChecked() && !Config.DISALLOW_REGISTRATION_IN_UI;
|
||||||
|
}
|
||||||
if (mUsernameMode && binding.accountJid.getText().toString().contains("@")) {
|
if (mUsernameMode && binding.accountJid.getText().toString().contains("@")) {
|
||||||
binding.accountJidLayout.setError(getString(R.string.invalid_username));
|
binding.accountJidLayout.setError(getString(R.string.invalid_username));
|
||||||
removeErrorsOnAllBut(binding.accountJidLayout);
|
removeErrorsOnAllBut(binding.accountJidLayout);
|
||||||
|
@ -395,7 +402,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmppConnectionService.getAccounts().size() == 0 && Config.MAGIC_CREATE_DOMAIN != null) {
|
if (xmppConnectionService.getAccounts().size() == 0 && Config.MAGIC_CREATE_DOMAIN != null) {
|
||||||
Intent intent = SignupUtils.getSignUpIntent(this);
|
Intent intent = SignupUtils.getSignUpIntent(this, mForceRegister != null && mForceRegister);
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -676,6 +683,9 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
||||||
}
|
}
|
||||||
boolean init = intent.getBooleanExtra("init", false);
|
boolean init = intent.getBooleanExtra("init", false);
|
||||||
boolean openedFromNotification = intent.getBooleanExtra(EXTRA_OPENED_FROM_NOTIFICATION, false);
|
boolean openedFromNotification = intent.getBooleanExtra(EXTRA_OPENED_FROM_NOTIFICATION, false);
|
||||||
|
Log.d(Config.LOGTAG,"extras "+intent.getExtras());
|
||||||
|
this.mForceRegister = intent.hasExtra(EXTRA_FORCE_REGISTER) ? intent.getBooleanExtra(EXTRA_FORCE_REGISTER,false) : null;
|
||||||
|
Log.d(Config.LOGTAG,"force register="+mForceRegister);
|
||||||
this.mInitMode = init || this.jidToEdit == null;
|
this.mInitMode = init || this.jidToEdit == null;
|
||||||
this.messageFingerprint = intent.getStringExtra("fingerprint");
|
this.messageFingerprint = intent.getStringExtra("fingerprint");
|
||||||
if (!mInitMode) {
|
if (!mInitMode) {
|
||||||
|
@ -685,13 +695,24 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
||||||
} else {
|
} else {
|
||||||
this.binding.avater.setVisibility(View.GONE);
|
this.binding.avater.setVisibility(View.GONE);
|
||||||
configureActionBar(getSupportActionBar(), !(init && Config.MAGIC_CREATE_DOMAIN == null));
|
configureActionBar(getSupportActionBar(), !(init && Config.MAGIC_CREATE_DOMAIN == null));
|
||||||
setTitle(R.string.action_add_account);
|
if (mForceRegister != null) {
|
||||||
|
if (mForceRegister) {
|
||||||
|
setTitle(R.string.register_new_account);
|
||||||
|
} else {
|
||||||
|
setTitle(R.string.add_existing_account);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setTitle(R.string.action_add_account);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SharedPreferences preferences = getPreferences();
|
SharedPreferences preferences = getPreferences();
|
||||||
mUseTor = QuickConversationsService.isConversations() && preferences.getBoolean("use_tor", getResources().getBoolean(R.bool.use_tor));
|
mUseTor = QuickConversationsService.isConversations() && preferences.getBoolean("use_tor", getResources().getBoolean(R.bool.use_tor));
|
||||||
this.mShowOptions = mUseTor || (QuickConversationsService.isConversations() && preferences.getBoolean("show_connection_options", getResources().getBoolean(R.bool.show_connection_options)));
|
this.mShowOptions = mUseTor || (QuickConversationsService.isConversations() && preferences.getBoolean("show_connection_options", getResources().getBoolean(R.bool.show_connection_options)));
|
||||||
this.binding.namePort.setVisibility(mShowOptions ? View.VISIBLE : View.GONE);
|
this.binding.namePort.setVisibility(mShowOptions ? View.VISIBLE : View.GONE);
|
||||||
|
if (mForceRegister != null) {
|
||||||
|
this.binding.accountRegisterNew.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -967,7 +988,7 @@ public class EditAccountActivity extends OmemoActivity implements OnAccountUpdat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.binding.accountRegisterNew.setVisibility(View.GONE);
|
this.binding.accountRegisterNew.setVisibility(View.GONE);
|
||||||
} else if (this.mAccount.isOptionSet(Account.OPTION_REGISTER)) {
|
} else if (this.mAccount.isOptionSet(Account.OPTION_REGISTER) && mForceRegister == null) {
|
||||||
this.binding.accountRegisterNew.setVisibility(View.VISIBLE);
|
this.binding.accountRegisterNew.setVisibility(View.VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
this.binding.accountRegisterNew.setVisibility(View.GONE);
|
this.binding.accountRegisterNew.setVisibility(View.GONE);
|
||||||
|
|
|
@ -1,24 +1,20 @@
|
||||||
package eu.siacs.conversations.ui;
|
package eu.siacs.conversations.ui;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.Dialog;
|
||||||
import android.databinding.DataBindingUtil;
|
import android.databinding.DataBindingUtil;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.text.Editable;
|
||||||
import android.util.Log;
|
import android.text.TextWatcher;
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.AutoCompleteTextView;
|
|
||||||
import android.widget.Spinner;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
|
@ -29,7 +25,10 @@ import eu.siacs.conversations.ui.interfaces.OnBackendConnected;
|
||||||
import eu.siacs.conversations.ui.util.DelayedHintHelper;
|
import eu.siacs.conversations.ui.util.DelayedHintHelper;
|
||||||
import rocks.xmpp.addr.Jid;
|
import rocks.xmpp.addr.Jid;
|
||||||
|
|
||||||
public class EnterJidDialog extends DialogFragment implements OnBackendConnected {
|
public class EnterJidDialog extends DialogFragment implements OnBackendConnected, TextWatcher {
|
||||||
|
|
||||||
|
|
||||||
|
private static final List<String> SUSPICIOUS_DOMAINS = Arrays.asList("conference","muc","room","rooms","chat");
|
||||||
|
|
||||||
private OnEnterJidDialogPositiveListener mListener = null;
|
private OnEnterJidDialogPositiveListener mListener = null;
|
||||||
|
|
||||||
|
@ -39,12 +38,21 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
|
||||||
private static final String ACCOUNT_KEY = "account";
|
private static final String ACCOUNT_KEY = "account";
|
||||||
private static final String ALLOW_EDIT_JID_KEY = "allow_edit_jid";
|
private static final String ALLOW_EDIT_JID_KEY = "allow_edit_jid";
|
||||||
private static final String ACCOUNTS_LIST_KEY = "activated_accounts_list";
|
private static final String ACCOUNTS_LIST_KEY = "activated_accounts_list";
|
||||||
|
private static final String SANITY_CHECK_JID = "sanity_check_jid";
|
||||||
|
|
||||||
private KnownHostsAdapter knownHostsAdapter;
|
private KnownHostsAdapter knownHostsAdapter;
|
||||||
|
|
||||||
|
private EnterJidDialogBinding binding;
|
||||||
|
private AlertDialog dialog;
|
||||||
|
private boolean sanityCheckJid = false;
|
||||||
|
|
||||||
|
|
||||||
|
private boolean issuedWarning = false;
|
||||||
|
|
||||||
public static EnterJidDialog newInstance(final List<String> activatedAccounts,
|
public static EnterJidDialog newInstance(final List<String> activatedAccounts,
|
||||||
final String title, final String positiveButton,
|
final String title, final String positiveButton,
|
||||||
final String prefilledJid, final String account, boolean allowEditJid) {
|
final String prefilledJid, final String account,
|
||||||
|
boolean allowEditJid, final boolean sanity_check_jid) {
|
||||||
EnterJidDialog dialog = new EnterJidDialog();
|
EnterJidDialog dialog = new EnterJidDialog();
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putString(TITLE_KEY, title);
|
bundle.putString(TITLE_KEY, title);
|
||||||
|
@ -53,6 +61,7 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
|
||||||
bundle.putString(ACCOUNT_KEY, account);
|
bundle.putString(ACCOUNT_KEY, account);
|
||||||
bundle.putBoolean(ALLOW_EDIT_JID_KEY, allowEditJid);
|
bundle.putBoolean(ALLOW_EDIT_JID_KEY, allowEditJid);
|
||||||
bundle.putStringArrayList(ACCOUNTS_LIST_KEY, (ArrayList<String>) activatedAccounts);
|
bundle.putStringArrayList(ACCOUNTS_LIST_KEY, (ArrayList<String>) activatedAccounts);
|
||||||
|
bundle.putBoolean(SANITY_CHECK_JID, sanity_check_jid);
|
||||||
dialog.setArguments(bundle);
|
dialog.setArguments(bundle);
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
@ -77,9 +86,10 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
builder.setTitle(getArguments().getString(TITLE_KEY));
|
builder.setTitle(getArguments().getString(TITLE_KEY));
|
||||||
EnterJidDialogBinding binding = DataBindingUtil.inflate(getActivity().getLayoutInflater(), R.layout.enter_jid_dialog, null, false);
|
binding = DataBindingUtil.inflate(getActivity().getLayoutInflater(), R.layout.enter_jid_dialog, null, false);
|
||||||
this.knownHostsAdapter = new KnownHostsAdapter(getActivity(), R.layout.simple_list_item);
|
this.knownHostsAdapter = new KnownHostsAdapter(getActivity(), R.layout.simple_list_item);
|
||||||
binding.jid.setAdapter(this.knownHostsAdapter);
|
binding.jid.setAdapter(this.knownHostsAdapter);
|
||||||
|
binding.jid.addTextChangedListener(this);
|
||||||
String prefilledJid = getArguments().getString(PREFILLED_JID_KEY);
|
String prefilledJid = getArguments().getString(PREFILLED_JID_KEY);
|
||||||
if (prefilledJid != null) {
|
if (prefilledJid != null) {
|
||||||
binding.jid.append(prefilledJid);
|
binding.jid.append(prefilledJid);
|
||||||
|
@ -90,6 +100,7 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
|
||||||
binding.jid.setCursorVisible(false);
|
binding.jid.setCursorVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sanityCheckJid = getArguments().getBoolean(SANITY_CHECK_JID, false);
|
||||||
|
|
||||||
DelayedHintHelper.setHint(R.string.account_settings_example_jabber_id, binding.jid);
|
DelayedHintHelper.setHint(R.string.account_settings_example_jabber_id, binding.jid);
|
||||||
|
|
||||||
|
@ -110,14 +121,14 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
|
||||||
builder.setView(binding.getRoot());
|
builder.setView(binding.getRoot());
|
||||||
builder.setNegativeButton(R.string.cancel, null);
|
builder.setNegativeButton(R.string.cancel, null);
|
||||||
builder.setPositiveButton(getArguments().getString(POSITIVE_BUTTON_KEY), null);
|
builder.setPositiveButton(getArguments().getString(POSITIVE_BUTTON_KEY), null);
|
||||||
AlertDialog dialog = builder.create();
|
this.dialog = builder.create();
|
||||||
|
|
||||||
View.OnClickListener dialogOnClick = v -> {
|
View.OnClickListener dialogOnClick = v -> {
|
||||||
handleEnter(binding, account, dialog);
|
handleEnter(binding, account);
|
||||||
};
|
};
|
||||||
|
|
||||||
binding.jid.setOnEditorActionListener((v, actionId, event) -> {
|
binding.jid.setOnEditorActionListener((v, actionId, event) -> {
|
||||||
handleEnter(binding, account, dialog);
|
handleEnter(binding, account);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -126,7 +137,7 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleEnter(EnterJidDialogBinding binding, String account, Dialog dialog) {
|
private void handleEnter(EnterJidDialogBinding binding, String account) {
|
||||||
final Jid accountJid;
|
final Jid accountJid;
|
||||||
if (!binding.account.isEnabled() && account == null) {
|
if (!binding.account.isEnabled() && account == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -148,6 +159,21 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!issuedWarning && sanityCheckJid) {
|
||||||
|
if (contactJid.isDomainJid()) {
|
||||||
|
binding.jid.setError(getActivity().getString(R.string.this_looks_like_a_domain));
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add_anway);
|
||||||
|
issuedWarning = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (suspiciousSubDomain(contactJid.getDomain())) {
|
||||||
|
binding.jid.setError(getActivity().getString(R.string.this_looks_like_channel));
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add_anway);
|
||||||
|
issuedWarning = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mListener != null) {
|
if (mListener != null) {
|
||||||
try {
|
try {
|
||||||
if (mListener.onEnterJidDialogPositive(accountJid, contactJid)) {
|
if (mListener.onEnterJidDialogPositive(accountJid, contactJid)) {
|
||||||
|
@ -176,6 +202,24 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {
|
||||||
|
if (issuedWarning) {
|
||||||
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setText(R.string.add);
|
||||||
|
issuedWarning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public interface OnEnterJidDialogPositiveListener {
|
public interface OnEnterJidDialogPositiveListener {
|
||||||
boolean onEnterJidDialogPositive(Jid account, Jid contact) throws EnterJidDialog.JidError;
|
boolean onEnterJidDialogPositive(Jid account, Jid contact) throws EnterJidDialog.JidError;
|
||||||
}
|
}
|
||||||
|
@ -200,4 +244,9 @@ public class EnterJidDialog extends DialogFragment implements OnBackendConnected
|
||||||
}
|
}
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean suspiciousSubDomain(String domain) {
|
||||||
|
final String[] parts = domain.split("\\.");
|
||||||
|
return parts.length >= 3 && SUSPICIOUS_DOMAINS.contains(parts[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -384,6 +384,7 @@ public class SettingsActivity extends XmppActivity implements
|
||||||
reconnectAccounts();
|
reconnectAccounts();
|
||||||
} else if (name.equals("use_tor")) {
|
} else if (name.equals("use_tor")) {
|
||||||
reconnectAccounts();
|
reconnectAccounts();
|
||||||
|
xmppConnectionService.reinitializeMuclumbusService();
|
||||||
} else if (name.equals(AUTOMATIC_MESSAGE_DELETION)) {
|
} else if (name.equals(AUTOMATIC_MESSAGE_DELETION)) {
|
||||||
xmppConnectionService.expireOldMessages(true);
|
xmppConnectionService.expireOldMessages(true);
|
||||||
} else if (name.equals(THEME)) {
|
} else if (name.equals(THEME)) {
|
||||||
|
|
|
@ -98,6 +98,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
|
||||||
private List<String> mActivatedAccounts = new ArrayList<>();
|
private List<String> mActivatedAccounts = new ArrayList<>();
|
||||||
private EditText mSearchEditText;
|
private EditText mSearchEditText;
|
||||||
private AtomicBoolean mRequestedContactsPermission = new AtomicBoolean(false);
|
private AtomicBoolean mRequestedContactsPermission = new AtomicBoolean(false);
|
||||||
|
private AtomicBoolean mOpenedFab = new AtomicBoolean(false);
|
||||||
private boolean mHideOfflineContacts = false;
|
private boolean mHideOfflineContacts = false;
|
||||||
private boolean createdByViewIntent = false;
|
private boolean createdByViewIntent = false;
|
||||||
private MenuItem.OnActionExpandListener mOnActionExpandListener = new MenuItem.OnActionExpandListener() {
|
private MenuItem.OnActionExpandListener mOnActionExpandListener = new MenuItem.OnActionExpandListener() {
|
||||||
|
@ -304,6 +305,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
|
||||||
mInitialSearchValue.push("");
|
mInitialSearchValue.push("");
|
||||||
}
|
}
|
||||||
mRequestedContactsPermission.set(savedInstanceState != null && savedInstanceState.getBoolean("requested_contacts_permission",false));
|
mRequestedContactsPermission.set(savedInstanceState != null && savedInstanceState.getBoolean("requested_contacts_permission",false));
|
||||||
|
mOpenedFab.set(savedInstanceState != null && savedInstanceState.getBoolean("opened_fab",false));
|
||||||
binding.speedDial.setOnActionSelectedListener(actionItem -> {
|
binding.speedDial.setOnActionSelectedListener(actionItem -> {
|
||||||
final String searchString = mSearchEditText != null ? mSearchEditText.getText().toString() : null;
|
final String searchString = mSearchEditText != null ? mSearchEditText.getText().toString() : null;
|
||||||
final String prefilled;
|
final String prefilled;
|
||||||
|
@ -313,6 +315,9 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
|
||||||
prefilled = null;
|
prefilled = null;
|
||||||
}
|
}
|
||||||
switch (actionItem.getId()) {
|
switch (actionItem.getId()) {
|
||||||
|
case R.id.discover_public_channels:
|
||||||
|
startActivity(new Intent(this, ChannelDiscoveryActivity.class));
|
||||||
|
break;
|
||||||
case R.id.join_public_channel:
|
case R.id.join_public_channel:
|
||||||
showJoinConferenceDialog(prefilled);
|
showJoinConferenceDialog(prefilled);
|
||||||
break;
|
break;
|
||||||
|
@ -344,6 +349,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
|
||||||
Intent pendingIntent = pendingViewIntent.peek();
|
Intent pendingIntent = pendingViewIntent.peek();
|
||||||
savedInstanceState.putParcelable("intent", pendingIntent != null ? pendingIntent : getIntent());
|
savedInstanceState.putParcelable("intent", pendingIntent != null ? pendingIntent : getIntent());
|
||||||
savedInstanceState.putBoolean("requested_contacts_permission",mRequestedContactsPermission.get());
|
savedInstanceState.putBoolean("requested_contacts_permission",mRequestedContactsPermission.get());
|
||||||
|
savedInstanceState.putBoolean("opened_fab",mOpenedFab.get());
|
||||||
savedInstanceState.putBoolean("created_by_view_intent",createdByViewIntent);
|
savedInstanceState.putBoolean("created_by_view_intent",createdByViewIntent);
|
||||||
if (mMenuSearchView != null && mMenuSearchView.isActionViewExpanded()) {
|
if (mMenuSearchView != null && mMenuSearchView.isActionViewExpanded()) {
|
||||||
savedInstanceState.putString("search", mSearchEditText != null ? mSearchEditText.getText().toString() : null);
|
savedInstanceState.putString("search", mSearchEditText != null ? mSearchEditText.getText().toString() : null);
|
||||||
|
@ -489,7 +495,8 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
|
||||||
getString(R.string.add),
|
getString(R.string.add),
|
||||||
prefilledJid,
|
prefilledJid,
|
||||||
null,
|
null,
|
||||||
invite == null || !invite.hasFingerprints()
|
invite == null || !invite.hasFingerprints(),
|
||||||
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
dialog.setOnEnterJidDialogPositiveListener((accountJid, contactJid) -> {
|
dialog.setOnEnterJidDialogPositiveListener((accountJid, contactJid) -> {
|
||||||
|
@ -781,15 +788,7 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
|
||||||
this.mPostponedActivityResult = null;
|
this.mPostponedActivityResult = null;
|
||||||
}
|
}
|
||||||
this.mActivatedAccounts.clear();
|
this.mActivatedAccounts.clear();
|
||||||
for (Account account : xmppConnectionService.getAccounts()) {
|
this.mActivatedAccounts.addAll(AccountUtils.getEnabledAccounts(xmppConnectionService));
|
||||||
if (account.getStatus() != Account.State.DISABLED) {
|
|
||||||
if (Config.DOMAIN_LOCK != null) {
|
|
||||||
this.mActivatedAccounts.add(account.getJid().getLocal());
|
|
||||||
} else {
|
|
||||||
this.mActivatedAccounts.add(account.getJid().asBareJid().toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
configureHomeButton();
|
configureHomeButton();
|
||||||
Intent intent = pendingViewIntent.pop();
|
Intent intent = pendingViewIntent.pop();
|
||||||
if (intent != null && processViewIntent(intent)) {
|
if (intent != null && processViewIntent(intent)) {
|
||||||
|
@ -809,6 +808,9 @@ public class StartConversationActivity extends XmppActivity implements XmppConne
|
||||||
if (QuickConversationsService.isQuicksy()) {
|
if (QuickConversationsService.isQuicksy()) {
|
||||||
setRefreshing(xmppConnectionService.getQuickConversationsService().isSynchronizing());
|
setRefreshing(xmppConnectionService.getQuickConversationsService().isSynchronizing());
|
||||||
}
|
}
|
||||||
|
if (QuickConversationsService.isConversations() && AccountUtils.hasEnabledAccounts(xmppConnectionService) && this.contacts.size() == 0 && this.conferences.size() == 0 && mOpenedFab.compareAndSet(false,true)) {
|
||||||
|
binding.speedDial.open();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean processViewIntent(@NonNull Intent intent) {
|
protected boolean processViewIntent(@NonNull Intent intent) {
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
package eu.siacs.conversations.ui.adapter;
|
||||||
|
|
||||||
|
import android.databinding.DataBindingUtil;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v7.recyclerview.extensions.ListAdapter;
|
||||||
|
import android.support.v7.util.DiffUtil;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.R;
|
||||||
|
import eu.siacs.conversations.databinding.SearchResultItemBinding;
|
||||||
|
import eu.siacs.conversations.http.services.MuclumbusService;
|
||||||
|
import eu.siacs.conversations.ui.util.AvatarWorkerTask;
|
||||||
|
|
||||||
|
public class ChannelSearchResultAdapter extends ListAdapter<MuclumbusService.Room, ChannelSearchResultAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
private OnChannelSearchResultSelected listener;
|
||||||
|
|
||||||
|
private static final DiffUtil.ItemCallback<MuclumbusService.Room> DIFF = new DiffUtil.ItemCallback<MuclumbusService.Room>() {
|
||||||
|
@Override
|
||||||
|
public boolean areItemsTheSame(@NonNull MuclumbusService.Room a, @NonNull MuclumbusService.Room b) {
|
||||||
|
return a.address != null && a.address.equals(b.address);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean areContentsTheSame(@NonNull MuclumbusService.Room a, @NonNull MuclumbusService.Room b) {
|
||||||
|
return a.equals(b);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public ChannelSearchResultAdapter() {
|
||||||
|
super(DIFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
|
||||||
|
return new ViewHolder(DataBindingUtil.inflate(LayoutInflater.from(viewGroup.getContext()), R.layout.search_result_item,viewGroup,false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
|
||||||
|
final MuclumbusService.Room searchResult = getItem(position);
|
||||||
|
viewHolder.binding.name.setText(searchResult.getName());
|
||||||
|
final String description = searchResult.getDescription();
|
||||||
|
if (TextUtils.isEmpty(description)) {
|
||||||
|
viewHolder.binding.description.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
viewHolder.binding.description.setText(description);
|
||||||
|
viewHolder.binding.description.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
viewHolder.binding.room.setText(searchResult.getRoom().asBareJid().toString());
|
||||||
|
AvatarWorkerTask.loadAvatar(searchResult, viewHolder.binding.avatar, R.dimen.avatar);
|
||||||
|
viewHolder.binding.getRoot().setOnClickListener(v -> listener.onChannelSearchResult(searchResult));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnChannelSearchResultSelectedListener(OnChannelSearchResultSelected listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
private final SearchResultItemBinding binding;
|
||||||
|
|
||||||
|
private ViewHolder(SearchResultItemBinding binding) {
|
||||||
|
super(binding.getRoot());
|
||||||
|
this.binding = binding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface OnChannelSearchResultSelected {
|
||||||
|
void onChannelSearchResult(MuclumbusService.Room result);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
package eu.siacs.conversations.ui.adapter;
|
package eu.siacs.conversations.ui.adapter;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.databinding.DataBindingUtil;
|
import android.databinding.DataBindingUtil;
|
||||||
|
@ -8,7 +7,6 @@ import android.graphics.Bitmap;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.support.annotation.AttrRes;
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
@ -17,7 +15,6 @@ import android.widget.ImageView;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
|
||||||
|
@ -26,7 +23,6 @@ import eu.siacs.conversations.databinding.MediaPreviewBinding;
|
||||||
import eu.siacs.conversations.ui.ConversationFragment;
|
import eu.siacs.conversations.ui.ConversationFragment;
|
||||||
import eu.siacs.conversations.ui.XmppActivity;
|
import eu.siacs.conversations.ui.XmppActivity;
|
||||||
import eu.siacs.conversations.ui.util.Attachment;
|
import eu.siacs.conversations.ui.util.Attachment;
|
||||||
import eu.siacs.conversations.ui.util.StyledAttributes;
|
|
||||||
|
|
||||||
public class MediaPreviewAdapter extends RecyclerView.Adapter<MediaPreviewAdapter.MediaPreviewViewHolder> {
|
public class MediaPreviewAdapter extends RecyclerView.Adapter<MediaPreviewAdapter.MediaPreviewViewHolder> {
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@ import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
@ -70,6 +72,7 @@ import eu.siacs.conversations.utils.GeoHelper;
|
||||||
import eu.siacs.conversations.utils.StylingHelper;
|
import eu.siacs.conversations.utils.StylingHelper;
|
||||||
import eu.siacs.conversations.utils.UIHelper;
|
import eu.siacs.conversations.utils.UIHelper;
|
||||||
import eu.siacs.conversations.xmpp.mam.MamReference;
|
import eu.siacs.conversations.xmpp.mam.MamReference;
|
||||||
|
import rocks.xmpp.addr.Jid;
|
||||||
|
|
||||||
public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextView.CopyHandler {
|
public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextView.CopyHandler {
|
||||||
|
|
||||||
|
@ -438,7 +441,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
body.setSpan(new DividerSpan(true), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
body.setSpan(new DividerSpan(true), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
}
|
}
|
||||||
boolean startsWithQuote = handleTextQuotes(body, darkBackground);
|
boolean startsWithQuote = handleTextQuotes(body, darkBackground);
|
||||||
if (message.getType() != Message.TYPE_PRIVATE) {
|
if (!message.isPrivateMessage()) {
|
||||||
if (hasMeCommand) {
|
if (hasMeCommand) {
|
||||||
body.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, nick.length(),
|
body.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 0, nick.length(),
|
||||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
@ -448,13 +451,8 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
if (message.getStatus() <= Message.STATUS_RECEIVED) {
|
if (message.getStatus() <= Message.STATUS_RECEIVED) {
|
||||||
privateMarker = activity.getString(R.string.private_message);
|
privateMarker = activity.getString(R.string.private_message);
|
||||||
} else {
|
} else {
|
||||||
final String to;
|
Jid cp = message.getCounterpart();
|
||||||
if (message.getCounterpart() != null) {
|
privateMarker = activity.getString(R.string.private_message_to, Strings.nullToEmpty(cp == null ? null : cp.getResource()));
|
||||||
to = message.getCounterpart().getResource();
|
|
||||||
} else {
|
|
||||||
to = "";
|
|
||||||
}
|
|
||||||
privateMarker = activity.getString(R.string.private_message_to, to);
|
|
||||||
}
|
}
|
||||||
body.insert(0, privateMarker);
|
body.insert(0, privateMarker);
|
||||||
int privateMarkerIndex = privateMarker.length();
|
int privateMarkerIndex = privateMarker.length();
|
||||||
|
@ -505,27 +503,27 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayDownloadableMessage(ViewHolder viewHolder, final Message message, String text) {
|
private void displayDownloadableMessage(ViewHolder viewHolder, final Message message, String text, final boolean darkBackground) {
|
||||||
|
toggleWhisperInfo(viewHolder, message, darkBackground);
|
||||||
viewHolder.image.setVisibility(View.GONE);
|
viewHolder.image.setVisibility(View.GONE);
|
||||||
viewHolder.messageBody.setVisibility(View.GONE);
|
|
||||||
viewHolder.audioPlayer.setVisibility(View.GONE);
|
viewHolder.audioPlayer.setVisibility(View.GONE);
|
||||||
viewHolder.download_button.setVisibility(View.VISIBLE);
|
viewHolder.download_button.setVisibility(View.VISIBLE);
|
||||||
viewHolder.download_button.setText(text);
|
viewHolder.download_button.setText(text);
|
||||||
viewHolder.download_button.setOnClickListener(v -> ConversationFragment.downloadFile(activity, message));
|
viewHolder.download_button.setOnClickListener(v -> ConversationFragment.downloadFile(activity, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayOpenableMessage(ViewHolder viewHolder, final Message message) {
|
private void displayOpenableMessage(ViewHolder viewHolder, final Message message, final boolean darkBackground) {
|
||||||
|
toggleWhisperInfo(viewHolder, message, darkBackground);
|
||||||
viewHolder.image.setVisibility(View.GONE);
|
viewHolder.image.setVisibility(View.GONE);
|
||||||
viewHolder.messageBody.setVisibility(View.GONE);
|
|
||||||
viewHolder.audioPlayer.setVisibility(View.GONE);
|
viewHolder.audioPlayer.setVisibility(View.GONE);
|
||||||
viewHolder.download_button.setVisibility(View.VISIBLE);
|
viewHolder.download_button.setVisibility(View.VISIBLE);
|
||||||
viewHolder.download_button.setText(activity.getString(R.string.open_x_file, UIHelper.getFileDescriptionString(activity, message)));
|
viewHolder.download_button.setText(activity.getString(R.string.open_x_file, UIHelper.getFileDescriptionString(activity, message)));
|
||||||
viewHolder.download_button.setOnClickListener(v -> openDownloadable(message));
|
viewHolder.download_button.setOnClickListener(v -> openDownloadable(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayLocationMessage(ViewHolder viewHolder, final Message message) {
|
private void displayLocationMessage(ViewHolder viewHolder, final Message message, final boolean darkBackground) {
|
||||||
|
toggleWhisperInfo(viewHolder, message, darkBackground);
|
||||||
viewHolder.image.setVisibility(View.GONE);
|
viewHolder.image.setVisibility(View.GONE);
|
||||||
viewHolder.messageBody.setVisibility(View.GONE);
|
|
||||||
viewHolder.audioPlayer.setVisibility(View.GONE);
|
viewHolder.audioPlayer.setVisibility(View.GONE);
|
||||||
viewHolder.download_button.setVisibility(View.VISIBLE);
|
viewHolder.download_button.setVisibility(View.VISIBLE);
|
||||||
viewHolder.download_button.setText(R.string.show_location);
|
viewHolder.download_button.setText(R.string.show_location);
|
||||||
|
@ -533,8 +531,8 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayAudioMessage(ViewHolder viewHolder, Message message, boolean darkBackground) {
|
private void displayAudioMessage(ViewHolder viewHolder, Message message, boolean darkBackground) {
|
||||||
|
toggleWhisperInfo(viewHolder, message, darkBackground);
|
||||||
viewHolder.image.setVisibility(View.GONE);
|
viewHolder.image.setVisibility(View.GONE);
|
||||||
viewHolder.messageBody.setVisibility(View.GONE);
|
|
||||||
viewHolder.download_button.setVisibility(View.GONE);
|
viewHolder.download_button.setVisibility(View.GONE);
|
||||||
final RelativeLayout audioPlayer = viewHolder.audioPlayer;
|
final RelativeLayout audioPlayer = viewHolder.audioPlayer;
|
||||||
audioPlayer.setVisibility(View.VISIBLE);
|
audioPlayer.setVisibility(View.VISIBLE);
|
||||||
|
@ -542,9 +540,9 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
this.audioPlayer.init(audioPlayer, message);
|
this.audioPlayer.init(audioPlayer, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayImageMessage(ViewHolder viewHolder, final Message message) {
|
private void displayImageMessage(ViewHolder viewHolder, final Message message, final boolean darkBackground) {
|
||||||
|
toggleWhisperInfo(viewHolder, message, darkBackground);
|
||||||
viewHolder.download_button.setVisibility(View.GONE);
|
viewHolder.download_button.setVisibility(View.GONE);
|
||||||
viewHolder.messageBody.setVisibility(View.GONE);
|
|
||||||
viewHolder.audioPlayer.setVisibility(View.GONE);
|
viewHolder.audioPlayer.setVisibility(View.GONE);
|
||||||
viewHolder.image.setVisibility(View.VISIBLE);
|
viewHolder.image.setVisibility(View.VISIBLE);
|
||||||
FileParams params = message.getFileParams();
|
FileParams params = message.getFileParams();
|
||||||
|
@ -571,6 +569,25 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
viewHolder.image.setOnClickListener(v -> openDownloadable(message));
|
viewHolder.image.setOnClickListener(v -> openDownloadable(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void toggleWhisperInfo(ViewHolder viewHolder, final Message message, final boolean darkBackground) {
|
||||||
|
if (message.isPrivateMessage()) {
|
||||||
|
final String privateMarker;
|
||||||
|
if (message.getStatus() <= Message.STATUS_RECEIVED) {
|
||||||
|
privateMarker = activity.getString(R.string.private_message);
|
||||||
|
} else {
|
||||||
|
Jid cp = message.getCounterpart();
|
||||||
|
privateMarker = activity.getString(R.string.private_message_to, Strings.nullToEmpty(cp == null ? null : cp.getResource()));
|
||||||
|
}
|
||||||
|
final SpannableString body = new SpannableString(privateMarker);
|
||||||
|
body.setSpan(new ForegroundColorSpan(getMessageTextColor(darkBackground, false)), 0, privateMarker.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
body.setSpan(new StyleSpan(Typeface.BOLD), 0, privateMarker.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
viewHolder.messageBody.setText(body);
|
||||||
|
viewHolder.messageBody.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
viewHolder.messageBody.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void loadMoreMessages(Conversation conversation) {
|
private void loadMoreMessages(Conversation conversation) {
|
||||||
conversation.setLastClearHistory(0, null);
|
conversation.setLastClearHistory(0, null);
|
||||||
activity.xmppConnectionService.updateConversation(conversation);
|
activity.xmppConnectionService.updateConversation(conversation);
|
||||||
|
@ -721,19 +738,19 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
final Transferable transferable = message.getTransferable();
|
final Transferable transferable = message.getTransferable();
|
||||||
if (message.isDeleted() || (transferable != null && transferable.getStatus() != Transferable.STATUS_UPLOADING)) {
|
if (message.isDeleted() || (transferable != null && transferable.getStatus() != Transferable.STATUS_UPLOADING)) {
|
||||||
if (transferable != null && transferable.getStatus() == Transferable.STATUS_OFFER) {
|
if (transferable != null && transferable.getStatus() == Transferable.STATUS_OFFER) {
|
||||||
displayDownloadableMessage(viewHolder, message, activity.getString(R.string.download_x_file, UIHelper.getFileDescriptionString(activity, message)));
|
displayDownloadableMessage(viewHolder, message, activity.getString(R.string.download_x_file, UIHelper.getFileDescriptionString(activity, message)), darkBackground);
|
||||||
} else if (transferable != null && transferable.getStatus() == Transferable.STATUS_OFFER_CHECK_FILESIZE) {
|
} else if (transferable != null && transferable.getStatus() == Transferable.STATUS_OFFER_CHECK_FILESIZE) {
|
||||||
displayDownloadableMessage(viewHolder, message, activity.getString(R.string.check_x_filesize, UIHelper.getFileDescriptionString(activity, message)));
|
displayDownloadableMessage(viewHolder, message, activity.getString(R.string.check_x_filesize, UIHelper.getFileDescriptionString(activity, message)), darkBackground);
|
||||||
} else {
|
} else {
|
||||||
displayInfoMessage(viewHolder, UIHelper.getMessagePreview(activity, message).first, darkBackground);
|
displayInfoMessage(viewHolder, UIHelper.getMessagePreview(activity, message).first, darkBackground);
|
||||||
}
|
}
|
||||||
} else if (message.isFileOrImage() && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) {
|
} else if (message.isFileOrImage() && message.getEncryption() != Message.ENCRYPTION_PGP && message.getEncryption() != Message.ENCRYPTION_DECRYPTION_FAILED) {
|
||||||
if (message.getFileParams().width > 0 && message.getFileParams().height > 0) {
|
if (message.getFileParams().width > 0 && message.getFileParams().height > 0) {
|
||||||
displayImageMessage(viewHolder, message);
|
displayImageMessage(viewHolder, message, darkBackground);
|
||||||
} else if (message.getFileParams().runtime > 0) {
|
} else if (message.getFileParams().runtime > 0) {
|
||||||
displayAudioMessage(viewHolder, message, darkBackground);
|
displayAudioMessage(viewHolder, message, darkBackground);
|
||||||
} else {
|
} else {
|
||||||
displayOpenableMessage(viewHolder, message);
|
displayOpenableMessage(viewHolder, message, darkBackground);
|
||||||
}
|
}
|
||||||
} else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
|
} else if (message.getEncryption() == Message.ENCRYPTION_PGP) {
|
||||||
if (account.isPgpDecryptionServiceConnected()) {
|
if (account.isPgpDecryptionServiceConnected()) {
|
||||||
|
@ -755,7 +772,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
displayInfoMessage(viewHolder, activity.getString(R.string.omemo_decryption_failed), darkBackground);
|
displayInfoMessage(viewHolder, activity.getString(R.string.omemo_decryption_failed), darkBackground);
|
||||||
} else {
|
} else {
|
||||||
if (message.isGeoUri()) {
|
if (message.isGeoUri()) {
|
||||||
displayLocationMessage(viewHolder, message);
|
displayLocationMessage(viewHolder, message, darkBackground);
|
||||||
} else if (message.bodyIsOnlyEmojis() && message.getType() != Message.TYPE_PRIVATE) {
|
} else if (message.bodyIsOnlyEmojis() && message.getType() != Message.TYPE_PRIVATE) {
|
||||||
displayEmojiMessage(viewHolder, message.getBody().trim(), darkBackground);
|
displayEmojiMessage(viewHolder, message.getBody().trim(), darkBackground);
|
||||||
} else if (message.treatAsDownloadable()) {
|
} else if (message.treatAsDownloadable()) {
|
||||||
|
@ -765,19 +782,22 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
|
||||||
displayDownloadableMessage(viewHolder,
|
displayDownloadableMessage(viewHolder,
|
||||||
message,
|
message,
|
||||||
activity.getString(R.string.check_x_filesize,
|
activity.getString(R.string.check_x_filesize,
|
||||||
UIHelper.getFileDescriptionString(activity, message)));
|
UIHelper.getFileDescriptionString(activity, message)),
|
||||||
|
darkBackground);
|
||||||
} else {
|
} else {
|
||||||
displayDownloadableMessage(viewHolder,
|
displayDownloadableMessage(viewHolder,
|
||||||
message,
|
message,
|
||||||
activity.getString(R.string.check_x_filesize_on_host,
|
activity.getString(R.string.check_x_filesize_on_host,
|
||||||
UIHelper.getFileDescriptionString(activity, message),
|
UIHelper.getFileDescriptionString(activity, message),
|
||||||
url.getHost()));
|
url.getHost()),
|
||||||
|
darkBackground);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
displayDownloadableMessage(viewHolder,
|
displayDownloadableMessage(viewHolder,
|
||||||
message,
|
message,
|
||||||
activity.getString(R.string.check_x_filesize,
|
activity.getString(R.string.check_x_filesize,
|
||||||
UIHelper.getFileDescriptionString(activity, message)));
|
UIHelper.getFileDescriptionString(activity, message)),
|
||||||
|
darkBackground);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
displayTextMessage(viewHolder, message, darkBackground, type);
|
displayTextMessage(viewHolder, message, darkBackground, type);
|
||||||
|
|
|
@ -111,6 +111,15 @@ public class Attachment implements Parcelable {
|
||||||
this.uuid = UUID.randomUUID();
|
this.uuid = UUID.randomUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean canBeSendInband(final List<Attachment> attachments) {
|
||||||
|
for(Attachment attachment : attachments) {
|
||||||
|
if (attachment.type != Type.LOCATION) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public static List<Attachment> of(final Context context, Uri uri, Type type) {
|
public static List<Attachment> of(final Context context, Uri uri, Type type) {
|
||||||
final String mime = type == Type.LOCATION ?null :MimeUtils.guessMimeTypeFromUri(context, uri);
|
final String mime = type == Type.LOCATION ?null :MimeUtils.guessMimeTypeFromUri(context, uri);
|
||||||
return Collections.singletonList(new Attachment(uri, type, mime));
|
return Collections.singletonList(new Attachment(uri, type, mime));
|
||||||
|
|
|
@ -179,7 +179,11 @@ public final class MucDetailsContextMenuHelper {
|
||||||
activity.privateMsgInMuc(conversation, user.getName());
|
activity.privateMsgInMuc(conversation, user.getName());
|
||||||
return true;
|
return true;
|
||||||
case R.id.invite:
|
case R.id.invite:
|
||||||
activity.xmppConnectionService.directInvite(conversation, jid);
|
if (user.getAffiliation().ranks(MucOptions.Affiliation.MEMBER)) {
|
||||||
|
activity.xmppConnectionService.directInvite(conversation, jid);
|
||||||
|
} else {
|
||||||
|
activity.xmppConnectionService.invite(conversation, jid);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -19,176 +19,184 @@ import android.view.KeyEvent;
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.view.inputmethod.InputConnection;
|
import android.view.inputmethod.InputConnection;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
|
|
||||||
public class EditMessage extends EmojiWrapperEditText {
|
public class EditMessage extends EmojiWrapperEditText {
|
||||||
|
|
||||||
private static final InputFilter SPAN_FILTER = (source, start, end, dest, dstart, dend) -> source instanceof Spanned ? source.toString() : source;
|
private static final InputFilter SPAN_FILTER = (source, start, end, dest, dstart, dend) -> source instanceof Spanned ? source.toString() : source;
|
||||||
protected Handler mTypingHandler = new Handler();
|
private final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
protected KeyboardListener keyboardListener;
|
protected Handler mTypingHandler = new Handler();
|
||||||
private OnCommitContentListener mCommitContentListener = null;
|
protected KeyboardListener keyboardListener;
|
||||||
private String[] mimeTypes = null;
|
private OnCommitContentListener mCommitContentListener = null;
|
||||||
private boolean isUserTyping = false;
|
private String[] mimeTypes = null;
|
||||||
protected Runnable mTypingTimeout = new Runnable() {
|
private boolean isUserTyping = false;
|
||||||
@Override
|
private final Runnable mTypingTimeout = new Runnable() {
|
||||||
public void run() {
|
@Override
|
||||||
if (isUserTyping && keyboardListener != null) {
|
public void run() {
|
||||||
keyboardListener.onTypingStopped();
|
if (isUserTyping && keyboardListener != null) {
|
||||||
isUserTyping = false;
|
keyboardListener.onTypingStopped();
|
||||||
}
|
isUserTyping = false;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
private boolean lastInputWasTab = false;
|
};
|
||||||
|
private boolean lastInputWasTab = false;
|
||||||
|
|
||||||
public EditMessage(Context context, AttributeSet attrs) {
|
public EditMessage(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EditMessage(Context context) {
|
public EditMessage(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent e) {
|
public boolean onKeyDown(int keyCode, KeyEvent e) {
|
||||||
if (keyCode == KeyEvent.KEYCODE_ENTER && !e.isShiftPressed()) {
|
if (keyCode == KeyEvent.KEYCODE_ENTER && !e.isShiftPressed()) {
|
||||||
lastInputWasTab = false;
|
lastInputWasTab = false;
|
||||||
if (keyboardListener != null && keyboardListener.onEnterPressed()) {
|
if (keyboardListener != null && keyboardListener.onEnterPressed()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (keyCode == KeyEvent.KEYCODE_TAB && !e.isAltPressed() && !e.isCtrlPressed()) {
|
} else if (keyCode == KeyEvent.KEYCODE_TAB && !e.isAltPressed() && !e.isCtrlPressed()) {
|
||||||
if (keyboardListener != null && keyboardListener.onTabPressed(this.lastInputWasTab)) {
|
if (keyboardListener != null && keyboardListener.onTabPressed(this.lastInputWasTab)) {
|
||||||
lastInputWasTab = true;
|
lastInputWasTab = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
lastInputWasTab = false;
|
lastInputWasTab = false;
|
||||||
}
|
}
|
||||||
return super.onKeyDown(keyCode, e);
|
return super.onKeyDown(keyCode, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAutofillType() {
|
public int getAutofillType() {
|
||||||
return AUTOFILL_TYPE_NONE;
|
return AUTOFILL_TYPE_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
|
|
||||||
super.onTextChanged(text, start, lengthBefore, lengthAfter);
|
|
||||||
lastInputWasTab = false;
|
|
||||||
if (this.mTypingHandler != null && this.keyboardListener != null) {
|
|
||||||
this.mTypingHandler.removeCallbacks(mTypingTimeout);
|
|
||||||
this.mTypingHandler.postDelayed(mTypingTimeout, Config.TYPING_TIMEOUT * 1000);
|
|
||||||
final int length = text.length();
|
|
||||||
if (!isUserTyping && length > 0) {
|
|
||||||
this.isUserTyping = true;
|
|
||||||
this.keyboardListener.onTypingStarted();
|
|
||||||
} else if (length == 0) {
|
|
||||||
this.isUserTyping = false;
|
|
||||||
this.keyboardListener.onTextDeleted();
|
|
||||||
}
|
|
||||||
this.keyboardListener.onTextChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKeyboardListener(KeyboardListener listener) {
|
@Override
|
||||||
this.keyboardListener = listener;
|
public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
|
||||||
if (listener != null) {
|
super.onTextChanged(text, start, lengthBefore, lengthAfter);
|
||||||
this.isUserTyping = false;
|
lastInputWasTab = false;
|
||||||
}
|
if (this.mTypingHandler != null && this.keyboardListener != null) {
|
||||||
}
|
executor.execute(() -> triggerKeyboardEvents(text.length()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
private void triggerKeyboardEvents(final int length) {
|
||||||
public boolean onTextContextMenuItem(int id) {
|
this.mTypingHandler.removeCallbacks(mTypingTimeout);
|
||||||
if (id == android.R.id.paste) {
|
this.mTypingHandler.postDelayed(mTypingTimeout, Config.TYPING_TIMEOUT * 1000);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (!isUserTyping && length > 0) {
|
||||||
return super.onTextContextMenuItem(android.R.id.pasteAsPlainText);
|
this.isUserTyping = true;
|
||||||
} else {
|
this.keyboardListener.onTypingStarted();
|
||||||
Editable editable = getEditableText();
|
} else if (length == 0) {
|
||||||
InputFilter[] filters = editable.getFilters();
|
this.isUserTyping = false;
|
||||||
InputFilter[] tempFilters = new InputFilter[filters != null ? filters.length + 1 : 1];
|
this.keyboardListener.onTextDeleted();
|
||||||
if (filters != null) {
|
}
|
||||||
System.arraycopy(filters, 0, tempFilters, 1, filters.length);
|
this.keyboardListener.onTextChanged();
|
||||||
}
|
}
|
||||||
tempFilters[0] = SPAN_FILTER;
|
|
||||||
editable.setFilters(tempFilters);
|
|
||||||
try {
|
|
||||||
return super.onTextContextMenuItem(id);
|
|
||||||
} finally {
|
|
||||||
editable.setFilters(filters);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return super.onTextContextMenuItem(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRichContentListener(String[] mimeTypes, OnCommitContentListener listener) {
|
public void setKeyboardListener(KeyboardListener listener) {
|
||||||
this.mimeTypes = mimeTypes;
|
this.keyboardListener = listener;
|
||||||
this.mCommitContentListener = listener;
|
if (listener != null) {
|
||||||
}
|
this.isUserTyping = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void insertAsQuote(String text) {
|
@Override
|
||||||
text = text.replaceAll("(\n *){2,}", "\n").replaceAll("(^|\n)", "$1> ").replaceAll("\n$", "");
|
public boolean onTextContextMenuItem(int id) {
|
||||||
Editable editable = getEditableText();
|
if (id == android.R.id.paste) {
|
||||||
int position = getSelectionEnd();
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
if (position == -1) position = editable.length();
|
return super.onTextContextMenuItem(android.R.id.pasteAsPlainText);
|
||||||
if (position > 0 && editable.charAt(position - 1) != '\n') {
|
} else {
|
||||||
editable.insert(position++, "\n");
|
Editable editable = getEditableText();
|
||||||
}
|
InputFilter[] filters = editable.getFilters();
|
||||||
editable.insert(position, text);
|
InputFilter[] tempFilters = new InputFilter[filters != null ? filters.length + 1 : 1];
|
||||||
position += text.length();
|
if (filters != null) {
|
||||||
editable.insert(position++, "\n");
|
System.arraycopy(filters, 0, tempFilters, 1, filters.length);
|
||||||
if (position < editable.length() && editable.charAt(position) != '\n') {
|
}
|
||||||
editable.insert(position, "\n");
|
tempFilters[0] = SPAN_FILTER;
|
||||||
}
|
editable.setFilters(tempFilters);
|
||||||
setSelection(position);
|
try {
|
||||||
}
|
return super.onTextContextMenuItem(id);
|
||||||
|
} finally {
|
||||||
|
editable.setFilters(filters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return super.onTextContextMenuItem(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public void setRichContentListener(String[] mimeTypes, OnCommitContentListener listener) {
|
||||||
public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
|
this.mimeTypes = mimeTypes;
|
||||||
final InputConnection ic = super.onCreateInputConnection(editorInfo);
|
this.mCommitContentListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
if (mimeTypes != null && mCommitContentListener != null && ic != null) {
|
public void insertAsQuote(String text) {
|
||||||
EditorInfoCompat.setContentMimeTypes(editorInfo, mimeTypes);
|
text = text.replaceAll("(\n *){2,}", "\n").replaceAll("(^|\n)", "$1> ").replaceAll("\n$", "");
|
||||||
return InputConnectionCompat.createWrapper(ic, editorInfo, (inputContentInfo, flags, opts) -> EditMessage.this.mCommitContentListener.onCommitContent(inputContentInfo, flags, opts, mimeTypes));
|
Editable editable = getEditableText();
|
||||||
} else {
|
int position = getSelectionEnd();
|
||||||
return ic;
|
if (position == -1) position = editable.length();
|
||||||
}
|
if (position > 0 && editable.charAt(position - 1) != '\n') {
|
||||||
}
|
editable.insert(position++, "\n");
|
||||||
|
}
|
||||||
|
editable.insert(position, text);
|
||||||
|
position += text.length();
|
||||||
|
editable.insert(position++, "\n");
|
||||||
|
if (position < editable.length() && editable.charAt(position) != '\n') {
|
||||||
|
editable.insert(position, "\n");
|
||||||
|
}
|
||||||
|
setSelection(position);
|
||||||
|
}
|
||||||
|
|
||||||
public void refreshIme() {
|
@Override
|
||||||
SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(getContext());
|
public InputConnection onCreateInputConnection(EditorInfo editorInfo) {
|
||||||
final boolean usingEnterKey = p.getBoolean("display_enter_key", getResources().getBoolean(R.bool.display_enter_key));
|
final InputConnection ic = super.onCreateInputConnection(editorInfo);
|
||||||
final boolean enterIsSend = p.getBoolean("enter_is_send", getResources().getBoolean(R.bool.enter_is_send));
|
|
||||||
|
|
||||||
if (usingEnterKey && enterIsSend) {
|
if (mimeTypes != null && mCommitContentListener != null && ic != null) {
|
||||||
setInputType(getInputType() & (~InputType.TYPE_TEXT_FLAG_MULTI_LINE));
|
EditorInfoCompat.setContentMimeTypes(editorInfo, mimeTypes);
|
||||||
setInputType(getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE));
|
return InputConnectionCompat.createWrapper(ic, editorInfo, (inputContentInfo, flags, opts) -> EditMessage.this.mCommitContentListener.onCommitContent(inputContentInfo, flags, opts, mimeTypes));
|
||||||
} else if (usingEnterKey) {
|
} else {
|
||||||
setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
|
return ic;
|
||||||
setInputType(getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE));
|
}
|
||||||
} else {
|
}
|
||||||
setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
|
|
||||||
setInputType(getInputType() | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface OnCommitContentListener {
|
public void refreshIme() {
|
||||||
boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags, Bundle opts, String[] mimeTypes);
|
SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
}
|
final boolean usingEnterKey = p.getBoolean("display_enter_key", getResources().getBoolean(R.bool.display_enter_key));
|
||||||
|
final boolean enterIsSend = p.getBoolean("enter_is_send", getResources().getBoolean(R.bool.enter_is_send));
|
||||||
|
|
||||||
public interface KeyboardListener {
|
if (usingEnterKey && enterIsSend) {
|
||||||
boolean onEnterPressed();
|
setInputType(getInputType() & (~InputType.TYPE_TEXT_FLAG_MULTI_LINE));
|
||||||
|
setInputType(getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE));
|
||||||
|
} else if (usingEnterKey) {
|
||||||
|
setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
|
||||||
|
setInputType(getInputType() & (~InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE));
|
||||||
|
} else {
|
||||||
|
setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_MULTI_LINE);
|
||||||
|
setInputType(getInputType() | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void onTypingStarted();
|
public interface OnCommitContentListener {
|
||||||
|
boolean onCommitContent(InputContentInfoCompat inputContentInfo, int flags, Bundle opts, String[] mimeTypes);
|
||||||
|
}
|
||||||
|
|
||||||
void onTypingStopped();
|
public interface KeyboardListener {
|
||||||
|
boolean onEnterPressed();
|
||||||
|
|
||||||
void onTextDeleted();
|
void onTypingStarted();
|
||||||
|
|
||||||
void onTextChanged();
|
void onTypingStopped();
|
||||||
|
|
||||||
boolean onTabPressed(boolean repeated);
|
void onTextDeleted();
|
||||||
}
|
|
||||||
|
void onTextChanged();
|
||||||
|
|
||||||
|
boolean onTabPressed(boolean repeated);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,10 @@ import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
|
@ -22,6 +24,30 @@ public class AccountUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean hasEnabledAccounts(final XmppConnectionService service) {
|
||||||
|
final List<Account> accounts = service.getAccounts();
|
||||||
|
for(Account account : accounts) {
|
||||||
|
if (account.isOptionSet(Account.OPTION_DISABLED)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> getEnabledAccounts(final XmppConnectionService service) {
|
||||||
|
ArrayList<String> accounts = new ArrayList<>();
|
||||||
|
for (Account account : service.getAccounts()) {
|
||||||
|
if (account.getStatus() != Account.State.DISABLED) {
|
||||||
|
if (Config.DOMAIN_LOCK != null) {
|
||||||
|
accounts.add(account.getJid().getLocal());
|
||||||
|
} else {
|
||||||
|
accounts.add(account.getJid().asBareJid().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return accounts;
|
||||||
|
}
|
||||||
|
|
||||||
public static Account getFirstEnabled(XmppConnectionService service) {
|
public static Account getFirstEnabled(XmppConnectionService service) {
|
||||||
final List<Account> accounts = service.getAccounts();
|
final List<Account> accounts = service.getAccounts();
|
||||||
for(Account account : accounts) {
|
for(Account account : accounts) {
|
||||||
|
|
|
@ -914,7 +914,7 @@ public class XmppConnection implements Runnable {
|
||||||
|
|
||||||
private void sendRegistryRequest() {
|
private void sendRegistryRequest() {
|
||||||
final IqPacket register = new IqPacket(IqPacket.TYPE.GET);
|
final IqPacket register = new IqPacket(IqPacket.TYPE.GET);
|
||||||
register.query("jabber:iq:register");
|
register.query(Namespace.REGISTER);
|
||||||
register.setTo(Jid.of(account.getServer()));
|
register.setTo(Jid.of(account.getServer()));
|
||||||
sendUnmodifiedIqPacket(register, (account, packet) -> {
|
sendUnmodifiedIqPacket(register, (account, packet) -> {
|
||||||
if (packet.getType() == IqPacket.TYPE.TIMEOUT) {
|
if (packet.getType() == IqPacket.TYPE.TIMEOUT) {
|
||||||
|
@ -923,12 +923,12 @@ public class XmppConnection implements Runnable {
|
||||||
if (packet.getType() == IqPacket.TYPE.ERROR) {
|
if (packet.getType() == IqPacket.TYPE.ERROR) {
|
||||||
throw new StateChangingError(Account.State.REGISTRATION_FAILED);
|
throw new StateChangingError(Account.State.REGISTRATION_FAILED);
|
||||||
}
|
}
|
||||||
final Element query = packet.query("jabber:iq:register");
|
final Element query = packet.query(Namespace.REGISTER);
|
||||||
if (query.hasChild("username") && (query.hasChild("password"))) {
|
if (query.hasChild("username") && (query.hasChild("password"))) {
|
||||||
final IqPacket register1 = new IqPacket(IqPacket.TYPE.SET);
|
final IqPacket register1 = new IqPacket(IqPacket.TYPE.SET);
|
||||||
final Element username = new Element("username").setContent(account.getUsername());
|
final Element username = new Element("username").setContent(account.getUsername());
|
||||||
final Element password = new Element("password").setContent(account.getPassword());
|
final Element password = new Element("password").setContent(account.getPassword());
|
||||||
register1.query("jabber:iq:register").addChild(username);
|
register1.query(Namespace.REGISTER).addChild(username);
|
||||||
register1.query().addChild(password);
|
register1.query().addChild(password);
|
||||||
register1.setFrom(account.getJid().asBareJid());
|
register1.setFrom(account.getJid().asBareJid());
|
||||||
sendUnmodifiedIqPacket(register1, registrationResponseListener, true);
|
sendUnmodifiedIqPacket(register1, registrationResponseListener, true);
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:background="?attr/color_background_primary"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
layout="@layout/toolbar" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
style="?android:attr/progressBarStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
app:layout_anchor="@+id/list" />
|
||||||
|
|
||||||
|
<android.support.design.widget.CoordinatorLayout
|
||||||
|
android:id="@+id/coordinator"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/color_background_primary">
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/list"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/color_background_primary"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layoutManager="android.support.v7.widget.LinearLayoutManager" />
|
||||||
|
</android.support.design.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</layout>
|
|
@ -2,8 +2,7 @@
|
||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="?attr/color_background_secondary">
|
android:background="?attr/color_background_secondary">
|
||||||
|
@ -14,6 +13,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_above="@+id/snackbar"
|
android:layout_above="@+id/snackbar"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:background="?attr/color_background_secondary"
|
android:background="?attr/color_background_secondary"
|
||||||
android:divider="@null"
|
android:divider="@null"
|
||||||
|
@ -21,23 +21,21 @@
|
||||||
android:listSelector="@android:color/transparent"
|
android:listSelector="@android:color/transparent"
|
||||||
android:stackFromBottom="true"
|
android:stackFromBottom="true"
|
||||||
android:transcriptMode="normal"
|
android:transcriptMode="normal"
|
||||||
tools:listitem="@layout/message_sent"
|
tools:listitem="@layout/message_sent"></ListView>
|
||||||
android:layout_alignParentLeft="true">
|
|
||||||
</ListView>
|
|
||||||
|
|
||||||
<android.support.design.widget.FloatingActionButton
|
<android.support.design.widget.FloatingActionButton
|
||||||
android:id="@+id/scroll_to_bottom_button"
|
android:id="@+id/scroll_to_bottom_button"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_alignBottom="@+id/messages_view"
|
android:layout_alignBottom="@+id/messages_view"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
android:alpha="0.85"
|
android:alpha="0.85"
|
||||||
app:backgroundTint="?attr/color_background_primary"
|
|
||||||
android:src="?attr/icon_scroll_down"
|
android:src="?attr/icon_scroll_down"
|
||||||
app:fabSize="mini"
|
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:useCompatPadding="true"
|
app:backgroundTint="?attr/color_background_primary"
|
||||||
android:layout_alignParentRight="true" />
|
app:fabSize="mini"
|
||||||
|
app:useCompatPadding="true" />
|
||||||
|
|
||||||
<eu.siacs.conversations.ui.widget.UnreadCountCustomView
|
<eu.siacs.conversations.ui.widget.UnreadCountCustomView
|
||||||
android:id="@+id/unread_count_custom_view"
|
android:id="@+id/unread_count_custom_view"
|
||||||
|
@ -45,75 +43,86 @@
|
||||||
android:layout_height="?attr/IconSize"
|
android:layout_height="?attr/IconSize"
|
||||||
android:layout_alignTop="@+id/scroll_to_bottom_button"
|
android:layout_alignTop="@+id/scroll_to_bottom_button"
|
||||||
android:layout_alignEnd="@+id/scroll_to_bottom_button"
|
android:layout_alignEnd="@+id/scroll_to_bottom_button"
|
||||||
|
android:layout_alignRight="@+id/scroll_to_bottom_button"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
android:elevation="8dp"
|
android:elevation="8dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:backgroundColor="?attr/unread_count"
|
app:backgroundColor="?attr/unread_count"
|
||||||
android:layout_alignRight="@+id/scroll_to_bottom_button"
|
tools:ignore="RtlCompat" />
|
||||||
tools:ignore="RtlCompat"
|
|
||||||
android:layout_marginRight="8dp" />
|
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/textsend"
|
android:id="@+id/textsend"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:background="?attr/color_background_primary"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentLeft="true">
|
android:layout_alignParentBottom="true"
|
||||||
|
android:background="?attr/color_background_primary">
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<LinearLayout
|
||||||
android:visibility="gone"
|
|
||||||
android:id="@+id/media_preview"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_toStartOf="@+id/textSendButton"
|
|
||||||
tools:listitem="@layout/media_preview"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
|
|
||||||
android:paddingTop="8dp"
|
|
||||||
android:requiresFadingEdge="horizontal"
|
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_toLeftOf="@+id/textSendButton">
|
|
||||||
|
|
||||||
</android.support.v7.widget.RecyclerView>
|
|
||||||
|
|
||||||
<eu.siacs.conversations.ui.widget.EditMessage
|
|
||||||
android:id="@+id/textinput"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_toStartOf="@+id/textSendButton"
|
android:layout_toStartOf="@+id/textSendButton"
|
||||||
android:background="?attr/color_background_primary"
|
android:layout_toLeftOf="@+id/textSendButton"
|
||||||
android:ems="10"
|
android:orientation="vertical">
|
||||||
style="@style/Widget.Conversations.EditText"
|
|
||||||
android:imeOptions="flagNoExtractUi|actionSend"
|
|
||||||
android:inputType="textShortMessage|textMultiLine|textCapSentences"
|
|
||||||
android:maxLines="8"
|
|
||||||
android:minHeight="48dp"
|
|
||||||
android:minLines="1"
|
|
||||||
android:paddingBottom="12dp"
|
|
||||||
android:paddingLeft="8dp"
|
|
||||||
android:paddingRight="8dp"
|
|
||||||
android:paddingTop="12dp"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:layout_toLeftOf="@+id/textSendButton">
|
|
||||||
|
|
||||||
<requestFocus/>
|
<TextView
|
||||||
</eu.siacs.conversations.ui.widget.EditMessage>
|
android:id="@+id/text_input_hint"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingRight="8dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.Conversations.Caption.Highlight"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/media_preview"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:requiresFadingEdge="horizontal"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
|
||||||
|
tools:listitem="@layout/media_preview">
|
||||||
|
|
||||||
|
</android.support.v7.widget.RecyclerView>
|
||||||
|
|
||||||
|
<eu.siacs.conversations.ui.widget.EditMessage
|
||||||
|
android:id="@+id/textinput"
|
||||||
|
style="@style/Widget.Conversations.EditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/color_background_primary"
|
||||||
|
android:ems="10"
|
||||||
|
android:imeOptions="flagNoExtractUi|actionSend"
|
||||||
|
android:inputType="textShortMessage|textMultiLine|textCapSentences"
|
||||||
|
android:maxLines="8"
|
||||||
|
android:minHeight="48dp"
|
||||||
|
android:minLines="1"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<requestFocus />
|
||||||
|
</eu.siacs.conversations.ui.widget.EditMessage>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/textSendButton"
|
android:id="@+id/textSendButton"
|
||||||
android:layout_width="48dp"
|
android:layout_width="48dp"
|
||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:background="?attr/color_background_primary"
|
android:background="?attr/color_background_primary"
|
||||||
android:contentDescription="@string/send_message"
|
android:contentDescription="@string/send_message"
|
||||||
android:src="?attr/ic_send_text_offline"
|
android:src="?attr/ic_send_text_offline" />
|
||||||
android:layout_alignParentRight="true" />
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
|
@ -121,9 +130,9 @@
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_above="@+id/textsend"
|
android:layout_above="@+id/textsend"
|
||||||
android:layout_marginBottom="4dp"
|
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
android:background="@drawable/snackbar"
|
android:background="@drawable/snackbar"
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
@ -133,28 +142,28 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_toStartOf="@+id/snackbar_action"
|
android:layout_toStartOf="@+id/snackbar_action"
|
||||||
|
android:layout_toLeftOf="@+id/snackbar_action"
|
||||||
android:paddingStart="24dp"
|
android:paddingStart="24dp"
|
||||||
android:textAppearance="@style/TextAppearance.Conversations.Body1.OnDark"
|
|
||||||
android:layout_alignParentLeft="true"
|
|
||||||
android:paddingLeft="24dp"
|
android:paddingLeft="24dp"
|
||||||
android:layout_toLeftOf="@+id/snackbar_action" />
|
android:textAppearance="@style/TextAppearance.Conversations.Body1.OnDark" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/snackbar_action"
|
android:id="@+id/snackbar_action"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:paddingBottom="16dp"
|
|
||||||
android:paddingLeft="24dp"
|
android:paddingLeft="24dp"
|
||||||
android:paddingRight="24dp"
|
|
||||||
android:paddingTop="16dp"
|
android:paddingTop="16dp"
|
||||||
|
android:paddingRight="24dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
android:textAllCaps="true"
|
android:textAllCaps="true"
|
||||||
android:textAppearance="@style/TextAppearance.Conversations.Body1.OnDark"
|
android:textAppearance="@style/TextAppearance.Conversations.Body1.OnDark"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold" />
|
||||||
android:layout_alignParentRight="true" />
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<eu.siacs.conversations.ui.widget.CopyTextView
|
||||||
|
android:id="@+id/message_body"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:autoLink="web"
|
||||||
|
android:longClickable="true"
|
||||||
|
android:textAppearance="@style/TextAppearance.Conversations.Body1"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/message_image"
|
android:id="@+id/message_image"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -12,14 +20,6 @@
|
||||||
android:longClickable="true"
|
android:longClickable="true"
|
||||||
android:scaleType="centerCrop"/>
|
android:scaleType="centerCrop"/>
|
||||||
|
|
||||||
<eu.siacs.conversations.ui.widget.CopyTextView
|
|
||||||
android:id="@+id/message_body"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:autoLink="web"
|
|
||||||
android:longClickable="true"
|
|
||||||
android:textAppearance="@style/TextAppearance.Conversations.Body1"/>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/download_button"
|
android:id="@+id/download_button"
|
||||||
style="?android:attr/buttonStyleSmall"
|
style="?android:attr/buttonStyleSmall"
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?selectableItemBackground"
|
||||||
|
android:padding="@dimen/list_padding">
|
||||||
|
|
||||||
|
<com.makeramen.roundedimageview.RoundedImageView
|
||||||
|
android:id="@+id/avatar"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
app:riv_corner_radius="2dp"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_toRightOf="@+id/avatar"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_marginLeft="@dimen/avatar_item_distance">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="@style/TextAppearance.Conversations.Subhead"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/description"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textAppearance="@style/TextAppearance.Conversations.Body1"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/room"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:textAppearance="@style/TextAppearance.Conversations.Body1.Secondary"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
</layout>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_search"
|
||||||
|
app:actionLayout="@layout/actionview_search"
|
||||||
|
android:icon="?attr/icon_search"
|
||||||
|
app:showAsAction="collapseActionView|always"
|
||||||
|
android:title="@string/search"/>
|
||||||
|
</menu>
|
|
@ -1,5 +1,9 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:id="@+id/discover_public_channels"
|
||||||
|
android:title="@string/discover_channels"
|
||||||
|
android:icon="@drawable/ic_search_white_24dp"/>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/join_public_channel"
|
android:id="@+id/join_public_channel"
|
||||||
android:title="@string/join_public_channel"
|
android:title="@string/join_public_channel"
|
||||||
|
|
|
@ -501,9 +501,6 @@ missatges.\n\nAra se us demanarà que desactiveu-las.</string>
|
||||||
<string name="security_error_invalid_file_access">Error de seguretat: accés al fitxer no vàlid</string>
|
<string name="security_error_invalid_file_access">Error de seguretat: accés al fitxer no vàlid</string>
|
||||||
<string name="no_application_to_share_uri">No s\'ha trobat cap aplicació que comparteixi URI</string>
|
<string name="no_application_to_share_uri">No s\'ha trobat cap aplicació que comparteixi URI</string>
|
||||||
<string name="share_uri_with">Comparteix l\'URI amb…</string>
|
<string name="share_uri_with">Comparteix l\'URI amb…</string>
|
||||||
<string name="welcome_text">Jabber és una xarxa de missatgeria instantània independent del proveïdor. Podeu
|
|
||||||
utilitzar aquest client amb el servidor de Jabber que trieu.\nPerò
|
|
||||||
per a la seva comoditat hem facilitat crear un compte a converses.im¹; un proveïdor especialment indicat per a l\'ús amb Conversations.</string>
|
|
||||||
<string name="welcome_text_quicksy"><![CDATA[Quicksy és un spin off de les populars Converses client Jabber/XMPP amb detecció automàtica de contactes. <br> <br> Vostè es registra amb el seu número de telèfon i Quicksy es basarà automàticament en els números de telèfon de la seva llibreta d\'adreces per suggerir-li possibles contactes. <br> <br> En registrar-se vostè accepta la nostra <a href="https://quicksy.im/#privacy"> política de privadesa </a>. ]]></string>
|
<string name="welcome_text_quicksy"><![CDATA[Quicksy és un spin off de les populars Converses client Jabber/XMPP amb detecció automàtica de contactes. <br> <br> Vostè es registra amb el seu número de telèfon i Quicksy es basarà automàticament en els números de telèfon de la seva llibreta d\'adreces per suggerir-li possibles contactes. <br> <br> En registrar-se vostè accepta la nostra <a href="https://quicksy.im/#privacy"> política de privadesa </a>. ]]></string>
|
||||||
<string name="magic_create_text">Us guiarem pel procés de creació d\'un compte a chat.sum7.eu.\nQuan
|
<string name="magic_create_text">Us guiarem pel procés de creació d\'un compte a chat.sum7.eu.\nQuan
|
||||||
trieu chat.sum7.eu com a proveïdor, podreu comunicar-vos amb els usuaris
|
trieu chat.sum7.eu com a proveïdor, podreu comunicar-vos amb els usuaris
|
||||||
|
|
|
@ -526,7 +526,6 @@
|
||||||
<string name="security_error_invalid_file_access">Sicherheitsfehler: Dateizugriff nicht erlaubt</string>
|
<string name="security_error_invalid_file_access">Sicherheitsfehler: Dateizugriff nicht erlaubt</string>
|
||||||
<string name="no_application_to_share_uri">Keine Anwendung zum Teilen der URI gefunden</string>
|
<string name="no_application_to_share_uri">Keine Anwendung zum Teilen der URI gefunden</string>
|
||||||
<string name="share_uri_with">Teile URI mit…</string>
|
<string name="share_uri_with">Teile URI mit…</string>
|
||||||
<string name="welcome_text">XMPP ist ein anbieterunabhängiges Instant Messaging Netzwerk. Du kannst diesen Client mit jedem beliebigen XMPP-Server nutzen.\nUm es dir leicht zu machen, haben wir die Möglichkeit geschaffen, ein Konto auf chat.sum7.eu anzulegen; ein Anbieter, der speziell für die Verwendung mit Conversations geeignet ist.</string>
|
|
||||||
<string name="welcome_text_quicksy"><![CDATA[Quicksy ist ein Ableger des beliebten XMPP-Clients Conversations mit automatischer Kontakterkennung.<br><br>Du registrierst dich mit deiner Telefonnummer und Quicksy wird automatisch auf der Grundlage der Telefonnummern in deinem Adressbuch mögliche Kontakte vorschlagen.<br><br>Mit der Anmeldung erklärst du dich mit unserer <a href="https://quicksy.im/#privacy">Datenschutzerklärung</a> einverstanden.]]></string>
|
<string name="welcome_text_quicksy"><![CDATA[Quicksy ist ein Ableger des beliebten XMPP-Clients Conversations mit automatischer Kontakterkennung.<br><br>Du registrierst dich mit deiner Telefonnummer und Quicksy wird automatisch auf der Grundlage der Telefonnummern in deinem Adressbuch mögliche Kontakte vorschlagen.<br><br>Mit der Anmeldung erklärst du dich mit unserer <a href="https://quicksy.im/#privacy">Datenschutzerklärung</a> einverstanden.]]></string>
|
||||||
<string name="agree_and_continue">Zustimmen & fortfahren</string>
|
<string name="agree_and_continue">Zustimmen & fortfahren</string>
|
||||||
<string name="magic_create_text">Wir führen dich durch den Prozess der Kontoerstellung auf chat.sum7.eu.\nWenn du chat.sum7.eu als Provider wählst, kannst du mit Nutzern anderer Anbieter kommunizieren, indem du ihnen deine vollständige XMPP-Adresse gibst.</string>
|
<string name="magic_create_text">Wir führen dich durch den Prozess der Kontoerstellung auf chat.sum7.eu.\nWenn du chat.sum7.eu als Provider wählst, kannst du mit Nutzern anderer Anbieter kommunizieren, indem du ihnen deine vollständige XMPP-Adresse gibst.</string>
|
||||||
|
@ -704,7 +703,7 @@
|
||||||
<string name="medium">Mittel</string>
|
<string name="medium">Mittel</string>
|
||||||
<string name="large">Groß</string>
|
<string name="large">Groß</string>
|
||||||
<string name="not_encrypted_for_this_device">Die Nachricht wurde nicht für dieses Gerät verschlüsselt.</string>
|
<string name="not_encrypted_for_this_device">Die Nachricht wurde nicht für dieses Gerät verschlüsselt.</string>
|
||||||
<string name="omemo_decryption_failed">Die OMEMO-Nachricht konnte nicht entschlüsselt werden.</string>
|
<string name="omemo_decryption_failed">OMEMO-Nachricht konnte nicht entschlüsselt werden.</string>
|
||||||
<string name="undo">rückgängig</string>
|
<string name="undo">rückgängig</string>
|
||||||
<string name="location_disabled">Standort teilen ist deaktiviert</string>
|
<string name="location_disabled">Standort teilen ist deaktiviert</string>
|
||||||
<string name="action_fix_to_location">Position fixieren</string>
|
<string name="action_fix_to_location">Position fixieren</string>
|
||||||
|
@ -754,7 +753,7 @@
|
||||||
<string name="view_users">Teilnehmer anzeigen</string>
|
<string name="view_users">Teilnehmer anzeigen</string>
|
||||||
<string name="group_chat_members">Teilnehmer</string>
|
<string name="group_chat_members">Teilnehmer</string>
|
||||||
<string name="media_browser">Medienbrowser</string>
|
<string name="media_browser">Medienbrowser</string>
|
||||||
<string name="security_violation_not_attaching_file">Die Datei wurde aufgrund von Sicherheitsverletzungen ausgelassen.</string>
|
<string name="security_violation_not_attaching_file">Datei wurde aufgrund von Sicherheitsverletzungen ausgelassen.</string>
|
||||||
<string name="pref_video_compression">Videoqualität</string>
|
<string name="pref_video_compression">Videoqualität</string>
|
||||||
<string name="pref_video_compression_summary">Geringere Qualität ermöglicht kleinere Dateien</string>
|
<string name="pref_video_compression_summary">Geringere Qualität ermöglicht kleinere Dateien</string>
|
||||||
<string name="video_360p">Mittel (360p)</string>
|
<string name="video_360p">Mittel (360p)</string>
|
||||||
|
@ -853,4 +852,14 @@
|
||||||
<string name="search_participants">Teilnehmer suchen</string>
|
<string name="search_participants">Teilnehmer suchen</string>
|
||||||
<string name="file_too_large">Datei ist zu groß</string>
|
<string name="file_too_large">Datei ist zu groß</string>
|
||||||
<string name="attach">Hinzufügen</string>
|
<string name="attach">Hinzufügen</string>
|
||||||
|
<string name="discover_channels">Channels entdecken</string>
|
||||||
|
<string name="search_channels">Channels suchen</string>
|
||||||
|
<string name="channel_discovery_opt_in_title">Mögliche Datenschutzverletzung!</string>
|
||||||
|
<string name="channel_discover_opt_in_message"><![CDATA[Die Channel-Entdeckung verwendet einen Drittanbieterservice namens <a href="https://search.jabbercat.org">search.jabbercat.org</a>.<br><br>Wenn du diese Funktion verwendest, werden deine IP-Adresse und deine Suchbegriffe an diesen Dienst übertragen. Weitere Informationen findest du in der <a href="https://search.jabbercat.org/privacy">Datenschutzerklärung</a>.]]></string>
|
||||||
|
<string name="i_already_have_an_account">Ich habe bereits ein Konto</string>
|
||||||
|
<string name="add_existing_account">Vorhandenes Konto hinzufügen</string>
|
||||||
|
<string name="register_new_account">Neues Konto erstellen</string>
|
||||||
|
<string name="this_looks_like_a_domain">Dies sieht aus wie eine Domain-Adresse</string>
|
||||||
|
<string name="add_anway">Trotzdem hinzufügen</string>
|
||||||
|
<string name="this_looks_like_channel">Dies sieht aus wie eine Channel-Adresse</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -522,8 +522,6 @@
|
||||||
<string name="pref_theme_options_summary">Επιλογή παλέτας χρωμάτων</string>
|
<string name="pref_theme_options_summary">Επιλογή παλέτας χρωμάτων</string>
|
||||||
<string name="pref_theme_light">Ανοιχτόχρωμο θέμα</string>
|
<string name="pref_theme_light">Ανοιχτόχρωμο θέμα</string>
|
||||||
<string name="pref_theme_dark">Σκουρόχρωμο θέμα</string>
|
<string name="pref_theme_dark">Σκουρόχρωμο θέμα</string>
|
||||||
<string name="pref_use_green_background">Πράσινο φόντο</string>
|
|
||||||
<string name="pref_use_green_background_summary">Χρήση πράσινου φόντου για εισερχόμενα μηνύματα</string>
|
|
||||||
<string name="unable_to_connect_to_keychain">Αδυναμία σύνδεσης στο OpenKeychain</string>
|
<string name="unable_to_connect_to_keychain">Αδυναμία σύνδεσης στο OpenKeychain</string>
|
||||||
<string name="this_device_is_no_longer_in_use">Αυτή η συσκευή δεν χρησιμοποιείται πλέον</string>
|
<string name="this_device_is_no_longer_in_use">Αυτή η συσκευή δεν χρησιμοποιείται πλέον</string>
|
||||||
<string name="type_pc">Υπολογιστής</string>
|
<string name="type_pc">Υπολογιστής</string>
|
||||||
|
|
|
@ -526,7 +526,6 @@
|
||||||
<string name="security_error_invalid_file_access">Error de seguridad: Acceso a fichero inválido</string>
|
<string name="security_error_invalid_file_access">Error de seguridad: Acceso a fichero inválido</string>
|
||||||
<string name="no_application_to_share_uri">No se ha encontrado ninguna aplicación para compartir la URI</string>
|
<string name="no_application_to_share_uri">No se ha encontrado ninguna aplicación para compartir la URI</string>
|
||||||
<string name="share_uri_with">Compartir URI con...</string>
|
<string name="share_uri_with">Compartir URI con...</string>
|
||||||
<string name="welcome_text">XMPP es una red de mensajería instantánea independiente del proveedor. Puedes usar este cliente con cualquier servidor XMPP que elijas.\nSin embargo, para tu conveniencia, hacemos de forma sencilla la creación de una cuenta en chat.sum7.eu; un proveedor especialmente especializado para el uso con Conversations</string>
|
|
||||||
<string name="welcome_text_quicksy"><![CDATA[Quicksy es un derivado del popular cliente XMPP Conversations con detección automática de contactos.<br><br>El registro se realiza con tu número de teléfono y Quicksy automáticamente—basado en los teléfonos de tu agenda de contactos—te sugerirá posibles contactos.<br><br>Registrándote en Quicksy aceptas nuestra <a href="https://quicksy.im/#privacy">política de privacidad</a>.]]> </string>
|
<string name="welcome_text_quicksy"><![CDATA[Quicksy es un derivado del popular cliente XMPP Conversations con detección automática de contactos.<br><br>El registro se realiza con tu número de teléfono y Quicksy automáticamente—basado en los teléfonos de tu agenda de contactos—te sugerirá posibles contactos.<br><br>Registrándote en Quicksy aceptas nuestra <a href="https://quicksy.im/#privacy">política de privacidad</a>.]]> </string>
|
||||||
<string name="agree_and_continue">Aceptar & continuar</string>
|
<string name="agree_and_continue">Aceptar & continuar</string>
|
||||||
<string name="magic_create_text">Te guiaremos durante el proceso de creación de la cuenta en chat.sum7.eu.\nCuando selecciones chat.sum7.eu como proveedor podrás comunicarte con usuarios de otros servidores proporcionándoles tu dirección XMPP completa. </string>
|
<string name="magic_create_text">Te guiaremos durante el proceso de creación de la cuenta en chat.sum7.eu.\nCuando selecciones chat.sum7.eu como proveedor podrás comunicarte con usuarios de otros servidores proporcionándoles tu dirección XMPP completa. </string>
|
||||||
|
@ -853,4 +852,14 @@
|
||||||
<string name="search_participants">Buscar participantes</string>
|
<string name="search_participants">Buscar participantes</string>
|
||||||
<string name="file_too_large">Archivo demasiado grande</string>
|
<string name="file_too_large">Archivo demasiado grande</string>
|
||||||
<string name="attach">Adjuntar</string>
|
<string name="attach">Adjuntar</string>
|
||||||
|
<string name="discover_channels">Descubrir canales</string>
|
||||||
|
<string name="search_channels">Buscar canales</string>
|
||||||
|
<string name="channel_discovery_opt_in_title">¡Posible violación de privacidad!</string>
|
||||||
|
<string name="channel_discover_opt_in_message"><![CDATA[La búsqueda de canales usa un servicio de terceros llamado search.jabbercat.org<a href="https://search.jabbercat.org">. <br><br>Usando esta funcionalidad transmitirás tu dirección IP y los términos buscados a este servicio. Ver su <a href="https://search.jabbercat.org/privacy">Política de Privacidad</a> para más información.]]></string>
|
||||||
|
<string name="i_already_have_an_account">Ya tengo una cuenta</string>
|
||||||
|
<string name="add_existing_account">Añadir una cuenta existente</string>
|
||||||
|
<string name="register_new_account">Registrar una cuenta nueva</string>
|
||||||
|
<string name="this_looks_like_a_domain">Esto parece una dirección de dominio</string>
|
||||||
|
<string name="add_anway">Añadir de todas formas</string>
|
||||||
|
<string name="this_looks_like_channel">Esto parece una dirección de un canal</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -502,6 +502,7 @@
|
||||||
<string name="no_storage_permission">Conversationsek kanpoko biltegirako sarbidea behar du</string>
|
<string name="no_storage_permission">Conversationsek kanpoko biltegirako sarbidea behar du</string>
|
||||||
<string name="no_camera_permission">Conversationsek kamerarako sarbidea behar du</string>
|
<string name="no_camera_permission">Conversationsek kamerarako sarbidea behar du</string>
|
||||||
<string name="sync_with_contacts">Kontaktuekin sinkronizatu</string>
|
<string name="sync_with_contacts">Kontaktuekin sinkronizatu</string>
|
||||||
|
<string name="sync_with_contacts_long">Conversationsek zerbitzariko zure kontaktuen zerrenda eta zure helbide liburu lokala uztartu nahi ditu haien izenak eta argazkiak erakusteko.\n\nConversationsek zure kontaktuak modu lokalean soilik irakurri eta uztartuko ditu, zure zerbitzarira kargatu gabe.\n\nJarraian baimenak eskatuko zaizkizu zure kontaktuetara sartu ahal izateko.</string>
|
||||||
<string name="notify_on_all_messages">Mezu guztiak jakinarazi</string>
|
<string name="notify_on_all_messages">Mezu guztiak jakinarazi</string>
|
||||||
<string name="notify_only_when_highlighted">Jakinarazi aipatua izaterakoan soilik</string>
|
<string name="notify_only_when_highlighted">Jakinarazi aipatua izaterakoan soilik</string>
|
||||||
<string name="notify_never">Jakinarazpenak ezgaituta</string>
|
<string name="notify_never">Jakinarazpenak ezgaituta</string>
|
||||||
|
@ -525,6 +526,7 @@
|
||||||
<string name="no_application_to_share_uri">Ez da aplikaziorik aurkitu URIa partekatzeko</string>
|
<string name="no_application_to_share_uri">Ez da aplikaziorik aurkitu URIa partekatzeko</string>
|
||||||
<string name="share_uri_with">URIa honekin partekatu...</string>
|
<string name="share_uri_with">URIa honekin partekatu...</string>
|
||||||
<string name="agree_and_continue">Onartu eta jarraitu</string>
|
<string name="agree_and_continue">Onartu eta jarraitu</string>
|
||||||
|
<string name="magic_create_text">conversations.im-en kontu bat sortzeko prozesuan zehar gidatuko zaitugu.\nconversations.im¹ hornitzaile bezala aukeratzerakoan beste hornitzaileen erabiltzaileekin komunikatzeko gai izango zara haiei zure XMPP helbide osoa emanez.</string>
|
||||||
<string name="your_full_jid_will_be">Zure XMPP helbide osoa hau izango da: %s</string>
|
<string name="your_full_jid_will_be">Zure XMPP helbide osoa hau izango da: %s</string>
|
||||||
<string name="create_account">Kontua sortu</string>
|
<string name="create_account">Kontua sortu</string>
|
||||||
<string name="use_own_provider">Nire hornitzale propioa erabili</string>
|
<string name="use_own_provider">Nire hornitzale propioa erabili</string>
|
||||||
|
@ -815,6 +817,7 @@
|
||||||
<string name="restore_backup">Babes-kopia berrezarri</string>
|
<string name="restore_backup">Babes-kopia berrezarri</string>
|
||||||
<string name="restore">Berrezarri</string>
|
<string name="restore">Berrezarri</string>
|
||||||
<string name="enter_password_to_restore">Sartu %s kontuaren pasahitza babes-kopia berrezartzeko.</string>
|
<string name="enter_password_to_restore">Sartu %s kontuaren pasahitza babes-kopia berrezartzeko.</string>
|
||||||
|
<string name="restore_warning">Ez erabili babes-kopiak berrezartzeko ezaugarria instalazio bat klonatzeko (aldi berean exekutatzeko). Babes-kopia bat berrezartzea migrazioetarako edo jatorrizko gailua galdu duzunerako da soilik.</string>
|
||||||
<string name="unable_to_restore_backup">Ezin izan da babes-kopia berrezarri.</string>
|
<string name="unable_to_restore_backup">Ezin izan da babes-kopia berrezarri.</string>
|
||||||
<string name="unable_to_decrypt_backup">Ezin izan da babes-kopia desenkriptatu. Pasahitza zuzena da?</string>
|
<string name="unable_to_decrypt_backup">Ezin izan da babes-kopia desenkriptatu. Pasahitza zuzena da?</string>
|
||||||
<string name="backup_channel_name">Babes-kopiak egin eta berrezarri</string>
|
<string name="backup_channel_name">Babes-kopiak egin eta berrezarri</string>
|
||||||
|
@ -846,4 +849,5 @@
|
||||||
<string name="manage_permission">Baimenak kudeatu</string>
|
<string name="manage_permission">Baimenak kudeatu</string>
|
||||||
<string name="search_participants">Parte-hartzaileak bilatu</string>
|
<string name="search_participants">Parte-hartzaileak bilatu</string>
|
||||||
<string name="file_too_large">Fitxategia handiegia da</string>
|
<string name="file_too_large">Fitxategia handiegia da</string>
|
||||||
|
<string name="attach">Erantsi</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -229,7 +229,7 @@
|
||||||
<string name="delete_bookmark">Supprimer le favori</string>
|
<string name="delete_bookmark">Supprimer le favori</string>
|
||||||
<string name="destroy_room">Détruire le chat en groupe</string>
|
<string name="destroy_room">Détruire le chat en groupe</string>
|
||||||
<string name="destroy_channel">Détruire le canal</string>
|
<string name="destroy_channel">Détruire le canal</string>
|
||||||
<string name="destroy_room_dialog">Voulez-vous vraiment détruire cette discussion de groupe? \ N \ n<b>Avertissement:</b> la discussion de groupe sera complètement supprimée du serveur.</string>
|
<string name="destroy_room_dialog">Voulez-vous vraiment détruire cette discussion de groupe?\n\n<b>Avertissement:</b> la discussion de groupe sera complètement supprimée du serveur.</string>
|
||||||
<string name="destroy_channel_dialog">Êtes-vous sûr de vouloir détruire ce canal public? \ On \ <b>Avertissement:</b> le canal sera complètement supprimé du serveur.</string>
|
<string name="destroy_channel_dialog">Êtes-vous sûr de vouloir détruire ce canal public? \ On \ <b>Avertissement:</b> le canal sera complètement supprimé du serveur.</string>
|
||||||
<string name="could_not_destroy_room">Impossible de détruire le chat en groupe</string>
|
<string name="could_not_destroy_room">Impossible de détruire le chat en groupe</string>
|
||||||
<string name="could_not_destroy_channel">Impossible de détruire le canal</string>
|
<string name="could_not_destroy_channel">Impossible de détruire le canal</string>
|
||||||
|
@ -502,8 +502,8 @@
|
||||||
<string name="no_storage_permission">Conversations a besoin d\'accéder au stockage externe</string>
|
<string name="no_storage_permission">Conversations a besoin d\'accéder au stockage externe</string>
|
||||||
<string name="no_camera_permission">Conversations a besoin d\'accéder à l\'appareil photo</string>
|
<string name="no_camera_permission">Conversations a besoin d\'accéder à l\'appareil photo</string>
|
||||||
<string name="sync_with_contacts">Synchroniser avec contacts</string>
|
<string name="sync_with_contacts">Synchroniser avec contacts</string>
|
||||||
<string name="sync_with_contacts_long">Conversations veut faire correspondre votre liste de contacts côté serveur avec votre carnet d\'adresses local pour afficher les noms complets et les avatars de vos contacts. \ N \ nLes conversions liront uniquement vos contacts et les feront correspondre localement sans les télécharger sur votre serveur. \ N \ nVous allez maintenant être invité à donner la permission d\'accéder à vos contacts.</string>
|
<string name="sync_with_contacts_long">Conversations veut faire correspondre votre liste de contacts côté serveur avec votre carnet d\'adresses local pour afficher les noms complets et les avatars de vos contacts.\n\nLes conversions liront uniquement vos contacts et les feront correspondre localement sans les télécharger sur votre serveur.\n\nVous allez maintenant être invité à donner la permission d\'accéder à vos contacts.</string>
|
||||||
<string name="sync_with_contacts_quicksy"><![CDATA[Quicksy a besoin d\'accéder aux numéros de téléphone de vos contacts pour vous suggérer des contacts éventuels déjà connectés.<br><br> Nous ne stockerons pas de copie de ces numéros. \ N \ nPour plus d\'informations, lisez notre <a href="https://quicksy.im/#privacy">politique de confidentialité</a>. <br><br>maintenant être invité à donner la permission d\'accéder à vos contacts.]]></string>
|
<string name="sync_with_contacts_quicksy"><![CDATA[Quicksy a besoin d\'accéder aux numéros de téléphone de vos contacts pour vous suggérer des contacts éventuels déjà connectés.<br><br> Nous ne stockerons pas de copie de ces numéros.\n\nPour plus d\'informations, lisez notre <a href="https://quicksy.im/#privacy">politique de confidentialité</a>. <br><br>maintenant être invité à donner la permission d\'accéder à vos contacts.]]></string>
|
||||||
<string name="notify_on_all_messages">Notifier pour tous les messages</string>
|
<string name="notify_on_all_messages">Notifier pour tous les messages</string>
|
||||||
<string name="notify_only_when_highlighted">Notifier seulement en cas de mention</string>
|
<string name="notify_only_when_highlighted">Notifier seulement en cas de mention</string>
|
||||||
<string name="notify_never">Notifications désactivées</string>
|
<string name="notify_never">Notifications désactivées</string>
|
||||||
|
@ -526,10 +526,9 @@
|
||||||
<string name="security_error_invalid_file_access">Erreur de sécurité : accès fichier non-valide</string>
|
<string name="security_error_invalid_file_access">Erreur de sécurité : accès fichier non-valide</string>
|
||||||
<string name="no_application_to_share_uri">Aucune application trouvée pour partager l\'URI</string>
|
<string name="no_application_to_share_uri">Aucune application trouvée pour partager l\'URI</string>
|
||||||
<string name="share_uri_with">Partager l\'URI avec...</string>
|
<string name="share_uri_with">Partager l\'URI avec...</string>
|
||||||
<string name="welcome_text">XMPP est un réseau de messagerie instantanée indépendant du fournisseur. Vous pouvez utiliser ce client avec le serveur XMPP de votre choix. \ NCependant, pour votre commodité, nous avons facilité la création d\'un compte pour les chat.sum7.eu; un fournisseur spécialement adapté à l\'utilisation avec Conversations.</string>
|
|
||||||
<string name="welcome_text_quicksy"><![CDATA[Quicksy est une version du populaire client XMPP Conversations avec découverte automatique des contacts.<br><br>Vous vous inscrivez avec votre numéro de téléphone et Quicksy va automatiquement, en fonction des numéros de votre carnet d’adresses, vous suggérer d’éventuels contacts.<br><br> en vous inscrivant, vous acceptez notre <a href="https://quicksy.im/#privacy">politique de confidentialité</a>.]]></string>
|
<string name="welcome_text_quicksy"><![CDATA[Quicksy est une version du populaire client XMPP Conversations avec découverte automatique des contacts.<br><br>Vous vous inscrivez avec votre numéro de téléphone et Quicksy va automatiquement, en fonction des numéros de votre carnet d’adresses, vous suggérer d’éventuels contacts.<br><br> en vous inscrivant, vous acceptez notre <a href="https://quicksy.im/#privacy">politique de confidentialité</a>.]]></string>
|
||||||
<string name="agree_and_continue">Accepter & continuer</string>
|
<string name="agree_and_continue">Accepter & continuer</string>
|
||||||
<string name="magic_create_text">Nous vous guiderons tout au long du processus de création d\'un compte sur chat.sum7.eu. \nLorsque vous sélectionnerez chat.sum7.eu en tant que fournisseur, vous pourrez communiquer avec les utilisateurs d\'autres fournisseurs en leur fournissant votre adresse XMPP complète.</string>
|
<string name="magic_create_text">Nous vous guiderons tout au long du processus de création d\'un compte sur chat.sum7.eu.\nLorsque vous sélectionnerez chat.sum7.eu en tant que fournisseur, vous pourrez communiquer avec les utilisateurs d\'autres fournisseurs en leur fournissant votre adresse XMPP complète.</string>
|
||||||
<string name="your_full_jid_will_be">Votre adresse XMPP complète sera : %s</string>
|
<string name="your_full_jid_will_be">Votre adresse XMPP complète sera : %s</string>
|
||||||
<string name="create_account">Créer un compte</string>
|
<string name="create_account">Créer un compte</string>
|
||||||
<string name="use_own_provider">Utiliser votre propre fournisseur</string>
|
<string name="use_own_provider">Utiliser votre propre fournisseur</string>
|
||||||
|
@ -852,4 +851,15 @@
|
||||||
<string name="manage_permission">Gérer les privilèges</string>
|
<string name="manage_permission">Gérer les privilèges</string>
|
||||||
<string name="search_participants">Rechercher des participants</string>
|
<string name="search_participants">Rechercher des participants</string>
|
||||||
<string name="file_too_large">Fichier trop volumineux</string>
|
<string name="file_too_large">Fichier trop volumineux</string>
|
||||||
|
<string name="attach">Joindre</string>
|
||||||
|
<string name="discover_channels">Découverte des canaux</string>
|
||||||
|
<string name="search_channels">Recherche des canaux</string>
|
||||||
|
<string name="channel_discovery_opt_in_title">Violation possible de la confidentialité !</string>
|
||||||
|
<string name="channel_discover_opt_in_message"><![CDATA[La découverte de chaînes utilise un service tiers appelé <a href="https://search.jabbercat.org">search.jabbercat.org</a> qui transmet votre adresse IP et les termes de recherche à ce service. Voir leur <a href="https://search.jabbercat.org/privacy">politique de confidentialité</a> pour plus d\'informations]]>.</string>
|
||||||
|
<string name="i_already_have_an_account">J\'ai déjà un compte</string>
|
||||||
|
<string name="add_existing_account">Ajouter un compte existant</string>
|
||||||
|
<string name="register_new_account">Enregistrer un nouveau compte</string>
|
||||||
|
<string name="this_looks_like_a_domain">Ceci ressemble à une adresse de domaine</string>
|
||||||
|
<string name="add_anway">Ajouter quand même</string>
|
||||||
|
<string name="this_looks_like_channel">Ceci ressemble à une adresse de canal</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -526,7 +526,6 @@
|
||||||
<string name="security_error_invalid_file_access">Fallo na seguridade: Acceso non válido ao ficheiro</string>
|
<string name="security_error_invalid_file_access">Fallo na seguridade: Acceso non válido ao ficheiro</string>
|
||||||
<string name="no_application_to_share_uri">Non se atopou un aplicativo para compartir URI</string>
|
<string name="no_application_to_share_uri">Non se atopou un aplicativo para compartir URI</string>
|
||||||
<string name="share_uri_with">Compartir URI con...</string>
|
<string name="share_uri_with">Compartir URI con...</string>
|
||||||
<string name="welcome_text">XMPP é un fornecedor de mensaxería instantánea independente da rede. Pode utilizar este cliente con calquera servidor XMPP que escolla.\nPorén, para a súa conveniencia, puxémolo fácil para crear unha conta en chat.sum7.eu; un fornecedor especialmente axeitado para o uso con Conversations.</string>
|
|
||||||
<string name="welcome_text_quicksy"><![CDATA[Quicksy é un derivado do popular cliente XMPP Conversations con descubrimento automático de contactos.<br><br>Pode rexistrarse co seu número de teléfono e Quicksy suxeriralle automáticamente —tomando os números da súa libreta de enderezos como referencia— posibles contactos para vostede.<br><br>Ao rexistarse vostede acepta a nosa <a href="https://quicksy.im/#privacy">política de intimidade</a>.]]></string>
|
<string name="welcome_text_quicksy"><![CDATA[Quicksy é un derivado do popular cliente XMPP Conversations con descubrimento automático de contactos.<br><br>Pode rexistrarse co seu número de teléfono e Quicksy suxeriralle automáticamente —tomando os números da súa libreta de enderezos como referencia— posibles contactos para vostede.<br><br>Ao rexistarse vostede acepta a nosa <a href="https://quicksy.im/#privacy">política de intimidade</a>.]]></string>
|
||||||
<string name="agree_and_continue">Aceptar & continuar</string>
|
<string name="agree_and_continue">Aceptar & continuar</string>
|
||||||
<string name="magic_create_text">Guiarémola a través do proceso de creación de unha conta en chat.sum7.eu.\nAo escoller a chat.sum7.eu como fornecedor poderá comunicar con usuarias de outros fornecedores proporcionándolles o seu enderezo XMPP completo.</string>
|
<string name="magic_create_text">Guiarémola a través do proceso de creación de unha conta en chat.sum7.eu.\nAo escoller a chat.sum7.eu como fornecedor poderá comunicar con usuarias de outros fornecedores proporcionándolles o seu enderezo XMPP completo.</string>
|
||||||
|
@ -853,4 +852,14 @@
|
||||||
<string name="search_participants">Buscar participantes</string>
|
<string name="search_participants">Buscar participantes</string>
|
||||||
<string name="file_too_large">Ficheiro demasiado grande</string>
|
<string name="file_too_large">Ficheiro demasiado grande</string>
|
||||||
<string name="attach">Anexar</string>
|
<string name="attach">Anexar</string>
|
||||||
|
<string name="discover_channels">Descubrir canles</string>
|
||||||
|
<string name="search_channels">Buscar canles</string>
|
||||||
|
<string name="channel_discovery_opt_in_title">Posible intrusión na intimidade!</string>
|
||||||
|
<string name="channel_discover_opt_in_message"><![CDATA[O descubrimento de canles utiliza un servizo de terceiros chamado <a href="https://search.jabbercat.org">search.jabbercat.org</a>.<br><br>Ao utilizar esta característica transmitirá o seu enderezo IP e os termos de busca a ese servizo. Lea a súa <a href="https://search.jabbercat.org/privacy">Política de Intimidade</a> para máis información.]]></string>
|
||||||
|
<string name="i_already_have_an_account">Xa teño unha conta</string>
|
||||||
|
<string name="add_existing_account">Engadir conta existente</string>
|
||||||
|
<string name="register_new_account">Rexistrar unha nova conta</string>
|
||||||
|
<string name="this_looks_like_a_domain">Esto semella un enderezo de dominio</string>
|
||||||
|
<string name="add_anway">Engadir igualmente</string>
|
||||||
|
<string name="this_looks_like_channel">Esto semella o enderezo de unha canle</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -526,7 +526,6 @@
|
||||||
<string name="security_error_invalid_file_access">Biztonsági hiba: Érvénytelen fájl hozzáférés</string>
|
<string name="security_error_invalid_file_access">Biztonsági hiba: Érvénytelen fájl hozzáférés</string>
|
||||||
<string name="no_application_to_share_uri">Nem találtunk URI-t használó alkalmazást</string>
|
<string name="no_application_to_share_uri">Nem találtunk URI-t használó alkalmazást</string>
|
||||||
<string name="share_uri_with">Megosztás URI-ként</string>
|
<string name="share_uri_with">Megosztás URI-ként</string>
|
||||||
<string name="welcome_text">Az XMPP egy szolgáltató független, azonnali üzenetküldő hálózat. Ezt az ügyfél programot bármelyik XMPP szerverhez használhatja.\nDe a könnyebbség kedvéért létrehozhat egy fiókot a chat.sum7.eu szolgáltatón is; ami kifejezetten a Conversations programmal való használatra lett tervezve.</string>
|
|
||||||
<string name="welcome_text_quicksy"><![CDATA[A Quicksy a népszerű Conversations XMPP kliens mellékhajtása automatikus kapcsolat felfedezéssel.<br><br>Regisztráljon a telefonszámával, és a Quicksy automatikusan – a címjegyzékében szereplő telefonszámok alapján – jelzi a lehetséges kapcsolatokat.<br><br>A regisztrációval elfogadja az<a href="https://quicksy.im/#privacy">adatvédelmi irányelveinket</a>.]]></string>
|
<string name="welcome_text_quicksy"><![CDATA[A Quicksy a népszerű Conversations XMPP kliens mellékhajtása automatikus kapcsolat felfedezéssel.<br><br>Regisztráljon a telefonszámával, és a Quicksy automatikusan – a címjegyzékében szereplő telefonszámok alapján – jelzi a lehetséges kapcsolatokat.<br><br>A regisztrációval elfogadja az<a href="https://quicksy.im/#privacy">adatvédelmi irányelveinket</a>.]]></string>
|
||||||
<string name="agree_and_continue">Egyetért & folytatás</string>
|
<string name="agree_and_continue">Egyetért & folytatás</string>
|
||||||
<string name="magic_create_text">Végigvezetjük a chat.sum7.eu-en való fiók létrehozás folyamatán.\nHa a chat.sum7.eu-et választja szolgáltatójának, akkor képes lesz kommunikálni a más szolgáltatóknál lévő felhasználókkal, ha megadja nekik a teljes XMPP címét.</string>
|
<string name="magic_create_text">Végigvezetjük a chat.sum7.eu-en való fiók létrehozás folyamatán.\nHa a chat.sum7.eu-et választja szolgáltatójának, akkor képes lesz kommunikálni a más szolgáltatóknál lévő felhasználókkal, ha megadja nekik a teljes XMPP címét.</string>
|
||||||
|
@ -852,4 +851,15 @@
|
||||||
<string name="manage_permission">Jogosultságok kezelése</string>
|
<string name="manage_permission">Jogosultságok kezelése</string>
|
||||||
<string name="search_participants">Résztvevők keresése</string>
|
<string name="search_participants">Résztvevők keresése</string>
|
||||||
<string name="file_too_large">A fájl túl nagy</string>
|
<string name="file_too_large">A fájl túl nagy</string>
|
||||||
|
<string name="attach">Csatol</string>
|
||||||
|
<string name="discover_channels">Csatornák felderítése</string>
|
||||||
|
<string name="search_channels">Csatornák keresése</string>
|
||||||
|
<string name="channel_discovery_opt_in_title">Magánélet lehetséges megsértése!</string>
|
||||||
|
<string name="channel_discover_opt_in_message"><![CDATA[A csatorna felderítés egy harmadik fél által biztosított szolgáltatást használ: <a href="https://search.jabbercat.org">search.jabbercat.org</a>.<br><br>Ezen funkció használata során át fog kerülni az IP címe és a keresési kifejezés ahhoz a szolgáltatáshoz. További információért tekintse meg az <a href="https://search.jabbercat.org/privacy">Adatvédelmi Irányelveiket</a>.]]></string>
|
||||||
|
<string name="i_already_have_an_account">Már rendelkezem fiókkal</string>
|
||||||
|
<string name="add_existing_account">Már létező fiók hozzáadása</string>
|
||||||
|
<string name="register_new_account">Új fiók létrehozása</string>
|
||||||
|
<string name="this_looks_like_a_domain">Ez egy domain címnek tűnik</string>
|
||||||
|
<string name="add_anway">Akkor is adja hozzá</string>
|
||||||
|
<string name="this_looks_like_channel">Ez egy csatorna címnek tűnik</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -526,7 +526,6 @@
|
||||||
<string name="security_error_invalid_file_access">Errore di sicurezza: accesso file non valido</string>
|
<string name="security_error_invalid_file_access">Errore di sicurezza: accesso file non valido</string>
|
||||||
<string name="no_application_to_share_uri">Nessuna applicazione trovata per condividere l\'URI</string>
|
<string name="no_application_to_share_uri">Nessuna applicazione trovata per condividere l\'URI</string>
|
||||||
<string name="share_uri_with">Condividi l\'URI con...</string>
|
<string name="share_uri_with">Condividi l\'URI con...</string>
|
||||||
<string name="welcome_text">XMPP è una rete di messaggeria istantanea indipendente dal provider. Puoi usare questo client con qualsiasi server XMPP scelto.\nComunque, per tua comodità, abbiamo semplificato la creazione di un account su chat.sum7.eu; un provider particolarmente adatto all\'uso con Conversations.</string>
|
|
||||||
<string name="welcome_text_quicksy"><![CDATA[Quicksy è una variante del popolare client XMPP Conversations con ricerca automatica dei contatti.<br><br>Ti registri con il tuo numero di telefono e Quicksy ti suggerirà—in base ai numeri di telefono nella tua rubrica—automaticamente i possibili contatti.<br><br>Registrandoti accetti la nostra <a href="https://quicksy.im/#privacy">politica sulla privacy</a>.]]></string>
|
<string name="welcome_text_quicksy"><![CDATA[Quicksy è una variante del popolare client XMPP Conversations con ricerca automatica dei contatti.<br><br>Ti registri con il tuo numero di telefono e Quicksy ti suggerirà—in base ai numeri di telefono nella tua rubrica—automaticamente i possibili contatti.<br><br>Registrandoti accetti la nostra <a href="https://quicksy.im/#privacy">politica sulla privacy</a>.]]></string>
|
||||||
<string name="agree_and_continue">Accetta e continua</string>
|
<string name="agree_and_continue">Accetta e continua</string>
|
||||||
<string name="magic_create_text">Ti guideremo nel processo di creazione di un account su chat.sum7.eu.\nQuando scegli chat.sum7.eu come provider potrai comunicare con utenti di altri provider dando il tuo indirizzo XMPP completo.</string>
|
<string name="magic_create_text">Ti guideremo nel processo di creazione di un account su chat.sum7.eu.\nQuando scegli chat.sum7.eu come provider potrai comunicare con utenti di altri provider dando il tuo indirizzo XMPP completo.</string>
|
||||||
|
@ -852,4 +851,15 @@
|
||||||
<string name="manage_permission">Gestisci i privilegi</string>
|
<string name="manage_permission">Gestisci i privilegi</string>
|
||||||
<string name="search_participants">Cerca partecipanti</string>
|
<string name="search_participants">Cerca partecipanti</string>
|
||||||
<string name="file_too_large">File troppo grande</string>
|
<string name="file_too_large">File troppo grande</string>
|
||||||
|
<string name="attach">Allega</string>
|
||||||
|
<string name="discover_channels">Individua i canali</string>
|
||||||
|
<string name="search_channels">Cerca i canali</string>
|
||||||
|
<string name="channel_discovery_opt_in_title">Possibile violazione della privacy!</string>
|
||||||
|
<string name="channel_discover_opt_in_message"><![CDATA[La ricerca dei canali usa un servizio di terze parti chiamato <a href="https://search.jabbercat.org">search.jabbercat.org</a>.<br><br>Usando questa opzione trasmetterai il tuo indirizzo IP e la stringa di ricerca al servizio. Controlla la loro <a href="https://search.jabbercat.org/privacy">Policy per la privacy</a> per maggiori informazioni.]]></string>
|
||||||
|
<string name="i_already_have_an_account">Ho già un account</string>
|
||||||
|
<string name="add_existing_account">Aggiungi un account pre-esistente</string>
|
||||||
|
<string name="register_new_account">Registra un nuovo account</string>
|
||||||
|
<string name="this_looks_like_a_domain">Questo sembra un indirizzo di dominio</string>
|
||||||
|
<string name="add_anway">Aggiungere comunque</string>
|
||||||
|
<string name="this_looks_like_channel">Questo sembra un indirizzo di canale</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -323,7 +323,7 @@
|
||||||
<string name="notification_backup_created_subtitle">De back-upbestanden zijn opgeslagen in %s</string>
|
<string name="notification_backup_created_subtitle">De back-upbestanden zijn opgeslagen in %s</string>
|
||||||
<string name="restoring_backup">Bezig met herstellen van back-up...</string>
|
<string name="restoring_backup">Bezig met herstellen van back-up...</string>
|
||||||
<string name="notification_restored_backup_title">Je back-up is hersteld</string>
|
<string name="notification_restored_backup_title">Je back-up is hersteld</string>
|
||||||
<string name="notification_restored_backup_subtitle">Vergeet niet om het account in te schakelen.</string>
|
<string name="notification_restored_backup_subtitle">Vergeet niet om de account in te schakelen.</string>
|
||||||
<string name="choose_file">Bestand kiezen</string>
|
<string name="choose_file">Bestand kiezen</string>
|
||||||
<string name="receiving_x_file">Ontvangen van %1$s (%2$d%% voltooid)</string>
|
<string name="receiving_x_file">Ontvangen van %1$s (%2$d%% voltooid)</string>
|
||||||
<string name="download_x_file">%s downloaden</string>
|
<string name="download_x_file">%s downloaden</string>
|
||||||
|
@ -851,4 +851,14 @@
|
||||||
<string name="search_participants">Deelnemers zoeken</string>
|
<string name="search_participants">Deelnemers zoeken</string>
|
||||||
<string name="file_too_large">Bestand te groot</string>
|
<string name="file_too_large">Bestand te groot</string>
|
||||||
<string name="attach">Bijvoegen</string>
|
<string name="attach">Bijvoegen</string>
|
||||||
|
<string name="discover_channels">Kanalen ontdekken</string>
|
||||||
|
<string name="search_channels">Kanalen doorzoeken</string>
|
||||||
|
<string name="channel_discovery_opt_in_title">Mogelijke privacyschending!</string>
|
||||||
|
<string name="channel_discover_opt_in_message"><![CDATA[Kanaalontdekking maakt gebruik van een derdepartijdienst genaamd <a href="https://search.jabbercat.org">search.jabbercat.org</a>.<br><br>Door deze functie te gebruiken, zullen je IP-adres en zoekopdrachten naar die dienst verstuurd worden. Bekijk hun <a href="https://search.jabbercat.org/privacy">privacybeleid</a> voor meer informatie.]]></string>
|
||||||
|
<string name="i_already_have_an_account">Ik heb al een account</string>
|
||||||
|
<string name="add_existing_account">Bestaande account toevoegen</string>
|
||||||
|
<string name="register_new_account">Nieuwe account registreren</string>
|
||||||
|
<string name="this_looks_like_a_domain">Dit lijkt op een domeinadres</string>
|
||||||
|
<string name="add_anway">Tóch toevoegen</string>
|
||||||
|
<string name="this_looks_like_channel">Dit lijkt op een kanaaladres</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -71,7 +71,7 @@
|
||||||
<string name="problem_connecting_to_account">Nie można połączyć się z kontem</string>
|
<string name="problem_connecting_to_account">Nie można połączyć się z kontem</string>
|
||||||
<string name="problem_connecting_to_accounts">Nie można połączyć się z wieloma kontami</string>
|
<string name="problem_connecting_to_accounts">Nie można połączyć się z wieloma kontami</string>
|
||||||
<string name="touch_to_fix">Dotknij tutaj aby zarządzać swoimi kontami</string>
|
<string name="touch_to_fix">Dotknij tutaj aby zarządzać swoimi kontami</string>
|
||||||
<string name="attach_file">Dołącz plik</string>
|
<string name="attach_file">Załącz plik</string>
|
||||||
<string name="not_in_roster">Kontakt nie należy do Twojej listy kontaktów. Czy chcesz go dodać?</string>
|
<string name="not_in_roster">Kontakt nie należy do Twojej listy kontaktów. Czy chcesz go dodać?</string>
|
||||||
<string name="add_contact">Dodaj kontakt</string>
|
<string name="add_contact">Dodaj kontakt</string>
|
||||||
<string name="send_failed">wysyłanie nie powiodło się</string>
|
<string name="send_failed">wysyłanie nie powiodło się</string>
|
||||||
|
@ -868,4 +868,15 @@ Administrator twojego serwera będzie mógł czytać twoje wiadomości, ale moż
|
||||||
<string name="manage_permission">Zarządzaj uprawnieniami</string>
|
<string name="manage_permission">Zarządzaj uprawnieniami</string>
|
||||||
<string name="search_participants">Wyszukaj uczestników</string>
|
<string name="search_participants">Wyszukaj uczestników</string>
|
||||||
<string name="file_too_large">Plik jest zbyt duży</string>
|
<string name="file_too_large">Plik jest zbyt duży</string>
|
||||||
|
<string name="attach">Załącz</string>
|
||||||
|
<string name="discover_channels">Odkryj kanały</string>
|
||||||
|
<string name="search_channels">Wyszukaj kanał</string>
|
||||||
|
<string name="channel_discovery_opt_in_title">Możliwe naruszenie prywatności!</string>
|
||||||
|
<string name="channel_discover_opt_in_message"><![CDATA[Odkrywanie kanałów używa usługi firmy trzeciej <a href="https://search.jabbercat.org">search.jabbercat.org</a>. <br><br>Używając tej funkcji twój adres IP oraz kryteria wyszukiwania zostaną wysłane do tej usługi. Sprawdź <a href="https://search.jabbercat.org/privacy">Politykę Prywatności</a> aby uzyskać więcej informacji.]]></string>
|
||||||
|
<string name="i_already_have_an_account">Już mam konto</string>
|
||||||
|
<string name="add_existing_account">Dodaj istniejące konto</string>
|
||||||
|
<string name="register_new_account">Zarejestruj nowe konto</string>
|
||||||
|
<string name="this_looks_like_a_domain">To wygląda jak nazwa domeny</string>
|
||||||
|
<string name="add_anway">Dodaj i tak</string>
|
||||||
|
<string name="this_looks_like_channel">To wygląda jak adres kanału</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -850,4 +850,15 @@
|
||||||
<string name="manage_permission">Gerenciar privilégios</string>
|
<string name="manage_permission">Gerenciar privilégios</string>
|
||||||
<string name="search_participants">Pesquisar participantes</string>
|
<string name="search_participants">Pesquisar participantes</string>
|
||||||
<string name="file_too_large">Arquivo muito grande</string>
|
<string name="file_too_large">Arquivo muito grande</string>
|
||||||
|
<string name="attach">Anexar</string>
|
||||||
|
<string name="discover_channels">Descobrir canais</string>
|
||||||
|
<string name="search_channels">Pesquisar canais</string>
|
||||||
|
<string name="channel_discovery_opt_in_title">Provável violação de privacidade!</string>
|
||||||
|
<string name="channel_discover_opt_in_message"><![CDATA[A descoberta de canais utiliza um serviço de terceiros chamado <a href="https://search.jabbercat.org">search.jabbercat.org</a>.<br><br>Ao usar esse recurso, você enviará o seu endereço IP e termos de pesquisa para esse serviço. Veja sua <a href="https://search.jabbercat.org/privacy">Política de Privacidade</a> para maiores informações.]]></string>
|
||||||
|
<string name="i_already_have_an_account">Eu já tenho uma conta.</string>
|
||||||
|
<string name="add_existing_account">Adicionar uma conta já existente</string>
|
||||||
|
<string name="register_new_account">Registrar uma nova conta</string>
|
||||||
|
<string name="this_looks_like_a_domain">Isso se parece com um endereço de domínio</string>
|
||||||
|
<string name="add_anway">Adicionar mesmo assim</string>
|
||||||
|
<string name="this_looks_like_channel">Isso se parece com um endereço de canal</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -861,4 +861,14 @@ sau chiar pierderea mesajelor.\nÎn continuare veți fi rugați să dezactivați
|
||||||
<string name="search_participants">Caută participanți</string>
|
<string name="search_participants">Caută participanți</string>
|
||||||
<string name="file_too_large">Fișier prea mare</string>
|
<string name="file_too_large">Fișier prea mare</string>
|
||||||
<string name="attach">Atașează</string>
|
<string name="attach">Atașează</string>
|
||||||
|
<string name="discover_channels">Descoperă canale publice</string>
|
||||||
|
<string name="search_channels">Caută canale publice</string>
|
||||||
|
<string name="channel_discovery_opt_in_title">Posibilă încălcare a intimității!</string>
|
||||||
|
<string name="channel_discover_opt_in_message"><![CDATA[Descoperirea de canale publice folosește un serviciu terț numit <a href="https://search.jabbercat.org">search.jabbercat.org</a>.<br><br>Folosind această funcție se va transmite adresa dumneavoastră IP și cuvintele căutate către acest serviciu. Pentru mai multe informații citiți <a href="https://search.jabbercat.org/privacy">Politica de confidențialitate</a> a serviciului.]]></string>
|
||||||
|
<string name="i_already_have_an_account">Eu am deja un cont</string>
|
||||||
|
<string name="add_existing_account">Adaugă un cont existent</string>
|
||||||
|
<string name="register_new_account">Înregistrează un cont nou</string>
|
||||||
|
<string name="this_looks_like_a_domain">Aceasta pare să fie o adresă de domeniu</string>
|
||||||
|
<string name="add_anway">Adaugă oricum</string>
|
||||||
|
<string name="this_looks_like_channel">Aceasta pare o adresă de canal</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -506,10 +506,6 @@
|
||||||
<string name="security_error_invalid_file_access">Помилка безпеки: Недійсний доступ до файлу</string>
|
<string name="security_error_invalid_file_access">Помилка безпеки: Недійсний доступ до файлу</string>
|
||||||
<string name="no_application_to_share_uri">Не знайдено програми, щоб поділитися URI</string>
|
<string name="no_application_to_share_uri">Не знайдено програми, щоб поділитися URI</string>
|
||||||
<string name="share_uri_with">Поділитися URI з…</string>
|
<string name="share_uri_with">Поділитися URI з…</string>
|
||||||
<string name="welcome_text">XMPP є незалежною мережею обміну миттєвими повідомленнями. .
|
|
||||||
Ви можете використовувати цей клієнт з будь-яким XMPP-сервером.
|
|
||||||
\nДля Вашої зручності Ви можете використовувати Conversations з сервісом chat.sum7.eu; який є оптимізований для використання з Conversations.
|
|
||||||
</string>
|
|
||||||
<string name="agree_and_continue">Прийняти й продовжити</string>
|
<string name="agree_and_continue">Прийняти й продовжити</string>
|
||||||
<string name="create_account">Створити обліковий запис</string>
|
<string name="create_account">Створити обліковий запис</string>
|
||||||
<string name="use_own_provider">Використати мого власного провайдера</string>
|
<string name="use_own_provider">Використати мого власного провайдера</string>
|
||||||
|
|
|
@ -527,7 +527,6 @@
|
||||||
<string name="no_application_to_share_uri">No application found to share URI</string>
|
<string name="no_application_to_share_uri">No application found to share URI</string>
|
||||||
<string name="share_uri_with">Share URI with…</string>
|
<string name="share_uri_with">Share URI with…</string>
|
||||||
<string name="welcome_header" translatable="false">Join the Conversation</string>
|
<string name="welcome_header" translatable="false">Join the Conversation</string>
|
||||||
<string name="welcome_text">XMPP is a provider independent instant messaging network. You can use this client with what ever XMPP server you choose.\nHowever for your convenience we made it easy to create an account on chat.sum7.eu; a provider specially suited for the use with Conversations.</string>
|
|
||||||
<string name="welcome_header_quicksy" translatable="false">Have some Quick Conversations</string>
|
<string name="welcome_header_quicksy" translatable="false">Have some Quick Conversations</string>
|
||||||
<string name="welcome_text_quicksy"><![CDATA[Quicksy is a spin off of the popular XMPP client Conversations with automatic contact discovery.<br><br>You sign up with your phone number and Quicksy will automatically—based on the phone numbers in your address book—suggest possible contacts to you.<br><br>By signing up you agree to our <a href="https://quicksy.im/#privacy">privacy policy</a>.]]></string>
|
<string name="welcome_text_quicksy"><![CDATA[Quicksy is a spin off of the popular XMPP client Conversations with automatic contact discovery.<br><br>You sign up with your phone number and Quicksy will automatically—based on the phone numbers in your address book—suggest possible contacts to you.<br><br>By signing up you agree to our <a href="https://quicksy.im/#privacy">privacy policy</a>.]]></string>
|
||||||
<string name="agree_and_continue">Agree & continue</string>
|
<string name="agree_and_continue">Agree & continue</string>
|
||||||
|
@ -855,4 +854,14 @@
|
||||||
<string name="search_participants">Search participants</string>
|
<string name="search_participants">Search participants</string>
|
||||||
<string name="file_too_large">File too large</string>
|
<string name="file_too_large">File too large</string>
|
||||||
<string name="attach">Attach</string>
|
<string name="attach">Attach</string>
|
||||||
|
<string name="discover_channels">Discover channels</string>
|
||||||
|
<string name="search_channels">Search channels</string>
|
||||||
|
<string name="channel_discovery_opt_in_title">Possible privacy violation!</string>
|
||||||
|
<string name="channel_discover_opt_in_message"><![CDATA[Channel discovery uses a third party service called <a href="https://search.jabbercat.org">search.jabbercat.org</a>.<br><br>Using this feature will transmit your IP address and search terms to that service. See their <a href="https://search.jabbercat.org/privacy">Privacy Policy</a> for more information.]]></string>
|
||||||
|
<string name="i_already_have_an_account">I already have an account</string>
|
||||||
|
<string name="add_existing_account">Add existing account</string>
|
||||||
|
<string name="register_new_account">Register new account</string>
|
||||||
|
<string name="this_looks_like_a_domain">This looks like a domain address</string>
|
||||||
|
<string name="add_anway">Add anyway</string>
|
||||||
|
<string name="this_looks_like_channel">This looks like a channel address</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -16,9 +16,12 @@ import eu.siacs.conversations.ui.VerifyActivity;
|
||||||
|
|
||||||
public class SignupUtils {
|
public class SignupUtils {
|
||||||
|
|
||||||
|
public static Intent getSignUpIntent(Activity activity, boolean ignored) {
|
||||||
|
return getSignUpIntent(activity);
|
||||||
|
}
|
||||||
|
|
||||||
public static Intent getSignUpIntent(Activity activity) {
|
public static Intent getSignUpIntent(Activity activity) {
|
||||||
final Intent intent = new Intent(activity, EnterPhoneNumberActivity.class);
|
return new Intent(activity, EnterPhoneNumberActivity.class);
|
||||||
return intent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Intent getRedirectionIntent(ConversationsActivity activity) {
|
public static Intent getRedirectionIntent(ConversationsActivity activity) {
|
||||||
|
|
Loading…
Reference in New Issue