Skip to content

Commit

Permalink
Merge branch 'master' into ninja-master
Browse files Browse the repository at this point in the history
# Conflicts:
#	build.gradle
#	src/conversations/res/values-bg/strings.xml
#	src/conversations/res/values-bn-rIN/strings.xml
#	src/conversations/res/values-da-rDK/strings.xml
#	src/conversations/res/values-de/strings.xml
#	src/conversations/res/values-el/strings.xml
#	src/conversations/res/values-es/strings.xml
#	src/conversations/res/values-eu/strings.xml
#	src/conversations/res/values-fi/strings.xml
#	src/conversations/res/values-fr/strings.xml
#	src/conversations/res/values-gl/strings.xml
#	src/conversations/res/values-hr/strings.xml
#	src/conversations/res/values-hu/strings.xml
#	src/conversations/res/values-ja/strings.xml
#	src/conversations/res/values-nl/strings.xml
#	src/conversations/res/values-pl/strings.xml
#	src/conversations/res/values-pt-rBR/strings.xml
#	src/conversations/res/values-ro-rRO/strings.xml
#	src/conversations/res/values-ru/strings.xml
#	src/conversations/res/values-sk/strings.xml
#	src/conversations/res/values-sq/strings.xml
#	src/conversations/res/values-sr/strings.xml
#	src/conversations/res/values-szl/strings.xml
#	src/conversations/res/values-tr-rTR/strings.xml
#	src/conversations/res/values-uk/strings.xml
#	src/conversations/res/values-zh-rCN/strings.xml
#	src/conversations/res/values/strings.xml
#	src/main/AndroidManifest.xml
#	src/main/java/eu/siacs/conversations/Config.java
#	src/main/java/eu/siacs/conversations/services/CallIntegration.java
#	src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java
#	src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
#	src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
#	src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java
#	src/main/res/mipmap-anydpi-v26/new_launcher_round.xml
#	src/main/res/values-ca/strings.xml
#	src/main/res/values-fa-rIR/strings.xml
#	src/main/res/values-fr/strings.xml
#	src/main/res/values-ja/strings.xml
#	src/main/res/values-ro-rRO/strings.xml
#	src/main/res/values-ru/strings.xml
#	src/main/res/values-sv/strings.xml
#	src/main/res/values-tr-rTR/strings.xml
#	src/main/res/values-zh-rCN/strings.xml
#	src/main/res/values-zh-rTW/strings.xml
#	src/main/res/values/about.xml
#	src/main/res/values/strings.xml
  • Loading branch information
christianrowlands committed Mar 21, 2024
2 parents 7c76481 + 400cbd8 commit e21b380
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 71 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Facile à utiliser, fiable, respectueux de votre batterie. Prend en charge les images, les conversations de groupe et le chiffrement de bout-en-bout.

Principes de conception :

* Être le plus joli et simple d'utilisation possible, sans compromis sur la sécurité ou la vie privée.
* S'appuyer sur des protocoles existants, bien établis
* Ne pas nécessiter de compte Google ou spécifiquement le Google Cloud Messaging (GCM)
* Nécessiter le moins de permissions possible

Fonctionnalités :
* Chiffrement de bout-en-bout avec au choix, <a href="http://conversations.im/omemo/">OMEMO</a> ou <a href="http://openpgp.org/about/">OpenPGP</a>
* Envoi et réception d'images
* Appels audio et vidéo chiffrés (DTLS-SRTP)
* Interface utilisateur intuitive qui suit les directives de conception d'Android
* Images / avatars pour vos contacts
* Synchronisation avec des clients de bureau
* Conférences (avec prise en charge des marque-pages)
* Intégration avec le carnet d'adresses
* Plusieurs comptes / boîte de réception unifiée
* Impact très faible sur l'autonomie de la batterie

Conversations facilite la création de compte sur le serveur gratuit conversations.im. Cependant Conversations fonctionne également avec n'importe quel autre serveur XMPP. De nombreux serveurs XMPP sont gérés par des bénévoles et gratuits.

Fonctionnalités de XMPP :

Conversations fonctionne avec n'importe quel serveur XMPP. Cependant XMPP est un protocole extensible. Ces extensions sont aussi standardisées dans ce que l'on appelle les XEP. Conversations en prend en charge quelques-unes pour rendre l'expérience utilisateur meilleure dans l'ensemble. Il y a des chances que votre serveur XMPP actuel ne les prenne pas en charge. Ainsi, pour tirer le meilleur parti de Conversations, vous devriez envisager soit de passer à un serveur XMPP qui le fait, ou encore mieux, gérer votre propre serveur XMPP pour vous et vos amis.

Ces XEP sont actuellement :

* XEP-0065: SOCKS5 Bytestreams (ou mod_proxy65). Sera utilisé pour transférer des fichiers si les deux correspondants sont derrière un pare-feu (NAT).
* XEP-0163: Personal Eventing Protocol pour les avatars
* XEP-0191: Blocking Command vous permet de mettre des spammeurs sur liste noire ou bloquer des contacts sans les retirer de vos contacts.
* XEP-0198: Stream Management permet à XMPP de survivre à des petites pannes de réseau et aux changements de la connexion TCP sous-jacente.
* XEP-0280: Message Carbons qui synchronise automatiquement les messages que vous envoyez à votre client de bureau et vous permet ainsi de passer sans heurt de votre client mobile à votre client de bureau et inversement dans une conversation.
* XEP-0237: Roster Versioning principalement pour économiser de la bande passante sur les connexions mobiles de mauvaise qualité.
* XEP-0313: Message Archive Management synchronise l'historique des messages avec le serveur. Retrouvez des messages qui ont été envoyés pendant que Conversations était hors ligne.
* XEP-0352: Client State Indication fait savoir au serveur si Conversations est ou n'est pas en arrière-plan. Permet au serveur d'économiser de la bande passante en différant des paquets non importants.
* XEP-0363: HTTP File Upload vous permet de partager des fichiers dans les conférences et avec des contacts hors-ligne. Nécessite un composant supplémentaire sur votre serveur.
11 changes: 5 additions & 6 deletions src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,8 @@
<activity
android:name=".ui.ShareWithActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:exported="false">
android:exported="true"
android:launchMode="singleTop">

<intent-filter>
<action android:name="android.intent.action.SEND" />
Expand Down Expand Up @@ -343,8 +343,7 @@
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".ui.AboutActivity"
android:parentActivityName=".ui.SettingsActivity"
android:exported="true">
android:parentActivityName=".ui.SettingsActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="eu.siacs.conversations.ui.SettingsActivity" />
Expand Down Expand Up @@ -375,8 +374,8 @@

<activity
android:name=".ui.ShortcutActivity"
android:label="@string/contact"
android:exported="false">
android:exported="true"
android:label="@string/contact">
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT" />
</intent-filter>
Expand Down
26 changes: 21 additions & 5 deletions src/main/java/eu/siacs/conversations/services/CallIntegration.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public class CallIntegration extends Connection {
private AudioDevice initialAudioDevice = null;
private final AtomicBoolean initialAudioDeviceConfigured = new AtomicBoolean(false);
private final AtomicBoolean delayedDestructionInitiated = new AtomicBoolean(false);
private final AtomicBoolean isDestroyed = new AtomicBoolean(false);

private List<CallEndpoint> availableEndpoints = Collections.emptyList();

Expand Down Expand Up @@ -363,7 +364,6 @@ public void error() {
final var toneGenerator = new ToneGenerator(AudioManager.STREAM_MUSIC, DEFAULT_VOLUME);
toneGenerator.startTone(ToneGenerator.TONE_CDMA_CALLDROP_LITE, 375);
this.destroyWithDelay(new DisconnectCause(DisconnectCause.ERROR, null), 375);
this.destroyWith(new DisconnectCause(DisconnectCause.ERROR, null));
}

public void retracted() {
Expand All @@ -389,7 +389,7 @@ private void destroyWithDelay(final DisconnectCause disconnectCause, final int d
JingleConnectionManager.SCHEDULED_EXECUTOR_SERVICE.schedule(
() -> {
this.setDisconnected(disconnectCause);
this.destroy();
this.destroyCallIntegration();
},
delay,
TimeUnit.MILLISECONDS);
Expand All @@ -404,7 +404,7 @@ private void destroyWith(final DisconnectCause disconnectCause) {
return;
}
this.setDisconnected(disconnectCause);
this.destroy();
this.destroyCallIntegration();
Log.d(Config.LOGTAG, "destroyed!");
}

Expand Down Expand Up @@ -447,9 +447,16 @@ private boolean selfManaged() {
}

public static boolean selfManaged(final Context context) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && hasSystemFeature(context);
}

public static boolean hasSystemFeature(final Context context) {
final var packageManager = context.getPackageManager();
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
&& packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
return packageManager.hasSystemFeature(PackageManager.FEATURE_TELECOM);
} else {
return packageManager.hasSystemFeature(PackageManager.FEATURE_CONNECTION_SERVICE);
}
}

public static boolean notSelfManaged(final Context context) {
Expand All @@ -472,6 +479,15 @@ public void setInitialAudioDevice(final AudioDevice audioDevice) {
audioManager.getAudioDevices()));
}

private void destroyCallIntegration() {
super.destroy();
this.isDestroyed.set(true);
}

public boolean isDestroyed() {
return this.isDestroyed.get();
}

/** AudioDevice is the names of possible audio devices that we currently support. */
public enum AudioDevice {
NONE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,14 +347,14 @@ public static void placeCall(
}
}

public static void addNewIncomingCall(
public static boolean addNewIncomingCall(
final Context context, final AbstractJingleConnection.Id id) {
if (CallIntegration.notSelfManaged(context)) {
Log.d(
Config.LOGTAG,
"not adding incoming call to TelecomManager on Android "
+ Build.VERSION.RELEASE);
return;
return true;
}
final var phoneAccountHandle =
CallIntegrationConnectionService.getHandle(context, id.account);
Expand All @@ -373,7 +373,9 @@ public static void addNewIncomingCall(
Config.LOGTAG,
id.account.getJid().asBareJid() + ": call integration not available",
e);
return false;
}
return true;
}

public static class ServiceConnectionService {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1139,31 +1139,31 @@ private Presence.Status getTargetPresence() {
}

public boolean isScreenLocked() {
final KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
final PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
final KeyguardManager keyguardManager = getSystemService(KeyguardManager.class);
final PowerManager powerManager = getSystemService(PowerManager.class);
final boolean locked = keyguardManager != null && keyguardManager.isKeyguardLocked();
final boolean interactive = powerManager != null && powerManager.isInteractive();
final boolean interactive;
try {
interactive = powerManager != null && powerManager.isInteractive();
} catch (final Exception e) {
return false;
}
return locked || !interactive;
}

private boolean isPhoneSilenced() {
final boolean notificationDnd;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final NotificationManager notificationManager = getSystemService(NotificationManager.class);
final int filter = notificationManager == null ? NotificationManager.INTERRUPTION_FILTER_UNKNOWN : notificationManager.getCurrentInterruptionFilter();
notificationDnd = filter >= NotificationManager.INTERRUPTION_FILTER_PRIORITY;
} else {
notificationDnd = false;
}
final AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
final NotificationManager notificationManager = getSystemService(NotificationManager.class);
final int filter = notificationManager == null ? NotificationManager.INTERRUPTION_FILTER_UNKNOWN : notificationManager.getCurrentInterruptionFilter();
final boolean notificationDnd = filter >= NotificationManager.INTERRUPTION_FILTER_PRIORITY;
final AudioManager audioManager = getSystemService(AudioManager.class);
final int ringerMode = audioManager == null ? AudioManager.RINGER_MODE_NORMAL : audioManager.getRingerMode();
try {
if (treatVibrateAsSilent()) {
return notificationDnd || ringerMode != AudioManager.RINGER_MODE_NORMAL;
} else {
return notificationDnd || ringerMode == AudioManager.RINGER_MODE_SILENT;
}
} catch (Throwable throwable) {
} catch (final Throwable throwable) {
Log.d(Config.LOGTAG, "platform bug in isPhoneSilenced (" + throwable.getMessage() + ")");
return notificationDnd;
}
Expand Down Expand Up @@ -1285,9 +1285,10 @@ protected int sizeOf(final String key, final Bitmap bitmap) {
editor.putBoolean(EventReceiver.SETTING_ENABLED_ACCOUNTS, hasEnabledAccounts).apply();
editor.apply();
toggleSetProfilePictureActivity(hasEnabledAccounts);
// reconfigurePushDistributor();

CallIntegrationConnectionService.togglePhoneAccountsAsync(this, this.accounts);
if (CallIntegration.hasSystemFeature(this)) {
CallIntegrationConnectionService.togglePhoneAccountsAsync(this, this.accounts);
}

restoreFromDatabase();

Expand Down Expand Up @@ -2466,7 +2467,9 @@ public void stopPresenceUpdatesTo(Contact contact) {
public void createAccount(final Account account) {
account.initAccountServices(this);
databaseBackend.createAccount(account);
CallIntegrationConnectionService.togglePhoneAccountAsync(this, account);
if (CallIntegration.hasSystemFeature(this)) {
CallIntegrationConnectionService.togglePhoneAccountAsync(this, account);
}
this.accounts.add(account);
this.reconnectAccountInBackground(account);
updateAccountUi();
Expand Down Expand Up @@ -2590,7 +2593,9 @@ public boolean updateAccount(final Account account) {
toggleForegroundService();
syncEnabledAccountSetting();
mChannelDiscoveryService.cleanCache();
CallIntegrationConnectionService.togglePhoneAccountAsync(this, account);
if (CallIntegration.hasSystemFeature(this)) {
CallIntegrationConnectionService.togglePhoneAccountAsync(this, account);
}
return true;
} else {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.databinding.DataBindingUtil;

import com.google.common.base.Strings;
Expand Down Expand Up @@ -130,7 +131,7 @@ public boolean onCreateOptionsMenu(final Menu menu) {
}

@Override
public boolean onMenuItemActionExpand(MenuItem item) {
public boolean onMenuItemActionExpand(@NonNull MenuItem item) {
mSearchEditText.post(() -> {
mSearchEditText.requestFocus();
final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
Expand All @@ -140,7 +141,7 @@ public boolean onMenuItemActionExpand(MenuItem item) {
}

@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
public boolean onMenuItemActionCollapse(@NonNull MenuItem item) {
final InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY);
mSearchEditText.setText("");
Expand Down Expand Up @@ -189,7 +190,7 @@ private void holdLoading() {
}

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
if (mMenuSearchView != null && mMenuSearchView.isActionViewExpanded()) {
savedInstanceState.putString("search", mSearchEditText != null ? mSearchEditText.getText().toString() : null);
}
Expand Down Expand Up @@ -248,40 +249,47 @@ public void onChannelSearchResult(final Room result) {
}

@Override
public boolean onContextItemSelected(MenuItem item) {
public boolean onContextItemSelected(@NonNull MenuItem item) {
final Room room = adapter.getCurrent();
if (room != null) {
switch (item.getItemId()) {
case R.id.share_with:
StartConversationActivity.shareAsChannel(this, room.address);
return true;
case R.id.open_join_dialog:
final Intent intent = new Intent(this, StartConversationActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra("force_dialog", true);
intent.setData(Uri.parse(String.format("xmpp:%s?join", room.address)));
startActivity(intent);
return true;
}
if (room == null) {
return false;
}
final int itemId = item.getItemId();
if (itemId == R.id.share_with) {
StartConversationActivity.shareAsChannel(this, room.address);
return true;
} else if (itemId == R.id.open_join_dialog) {
final Intent intent = new Intent(this, StartConversationActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra("force_dialog", true);
intent.setData(Uri.parse(String.format("xmpp:%s?join", room.address)));
startActivity(intent);
return true;
} else {
return false;
}
return false;
}

public void joinChannelSearchResult(String selectedAccount, Room result) {
final Jid jid = Config.DOMAIN_LOCK == null ? Jid.ofEscaped(selectedAccount) : Jid.ofLocalAndDomainEscaped(selectedAccount, Config.DOMAIN_LOCK);
public void joinChannelSearchResult(final String selectedAccount, final Room result) {
final Jid jid =
Config.DOMAIN_LOCK == null
? Jid.ofEscaped(selectedAccount)
: Jid.ofLocalAndDomainEscaped(selectedAccount, Config.DOMAIN_LOCK);
final boolean syncAutoJoin = getBooleanPreference("autojoin", R.bool.autojoin);
final Account account = xmppConnectionService.findAccountByJid(jid);
final Conversation conversation = xmppConnectionService.findOrCreateConversation(account, result.getRoom(), true, true, true);
Bookmark bookmark = conversation.getBookmark();
if (bookmark != null) {
if (!bookmark.autojoin() && syncAutoJoin) {
bookmark.setAutojoin(true);
xmppConnectionService.createBookmark(account, bookmark);
}
} else {
bookmark = new Bookmark(account, conversation.getJid().asBareJid());
final Conversation conversation =
xmppConnectionService.findOrCreateConversation(
account, result.getRoom(), true, true, true);
final var existingBookmark = conversation.getBookmark();
if (existingBookmark == null) {
final var bookmark = new Bookmark(account, conversation.getJid().asBareJid());
bookmark.setAutojoin(syncAutoJoin);
xmppConnectionService.createBookmark(account, bookmark);
} else {
if (!existingBookmark.autojoin() && syncAutoJoin) {
existingBookmark.setAutojoin(true);
xmppConnectionService.createBookmark(account, existingBookmark);
}
}
switchToConversation(conversation);
}
Expand Down
Loading

0 comments on commit e21b380

Please sign in to comment.