Merge remote-tracking branch 'refs/remotes/siacs/master'

This commit is contained in:
Christian Schneppe 2016-05-31 21:38:06 +02:00
commit c23642b8cd
13 changed files with 128 additions and 71 deletions

View file

@ -1,9 +1,16 @@
###Changelog
####Version 1.13.1
* add database importer from local storage as backup
* bug fixes
####Version 1.13.0
* changed applicationId
* play videos directly without touching play button
####Version 1.12.6
* bug fixes
* add database exporter to local storage as backup
####Version 1.12.5
* bug fixes

View file

@ -31,7 +31,7 @@ dependencies {
compile project(':libs:MemorizingTrustManager')
compile project(':libs:audiowife')
playstoreCompile 'com.google.android.gms:play-services-gcm:9.0.0'
playstoreCompile 'com.google.android.gms:play-services-gcm:9.0.1'
compile 'org.sufficientlysecure:openpgp-api:10.0'
compile 'com.soundcloud.android:android-crop:1.0.1@aar'
compile 'com.android.support:support-v13:24.0.0-beta1'
@ -55,8 +55,8 @@ dependencies {
compile 'com.github.bumptech.glide:glide:3.5.2'
compile 'com.github.chrisbanes:PhotoView:1.2.6'
compile 'com.github.rtoshiro.fullscreenvideoview:fullscreenvideoview:1.1.0'
compile 'com.google.android.gms:play-services-location:9.0.0'
compile 'com.google.android.gms:play-services-maps:9.0.0'
compile 'com.google.android.gms:play-services-location:9.0.1'
compile 'com.google.android.gms:play-services-maps:9.0.1'
}
ext {

View file

@ -93,7 +93,8 @@
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" />
<data android:host="jabber.pix-art.de" />
<data android:pathPrefix="/i/"/>
<data android:pathPrefix="/i/" />
<data android:pathPrefix="/j/" />
</intent-filter>
</activity>

View file

@ -19,7 +19,7 @@ public class Message extends AbstractEntity {
public static final String TABLENAME = "messages";
public static final String MERGE_SEPARATOR = "\n\u0004\n";
public static final String MERGE_SEPARATOR = "\n\u200B\n";
public static final int STATUS_RECEIVED = 0;
public static final int STATUS_UNSEND = 1;

View file

@ -219,6 +219,7 @@ public class HttpUploadConnection implements Transferable {
mXmppConnectionService.resendMessage(message, delayed);
}
} else {
Log.d(Config.LOGTAG,"http upload failed because response code was "+code);
fail();
}
} catch (IOException e) {

View file

@ -96,6 +96,7 @@ import eu.siacs.conversations.utils.ExceptionHelper;
import eu.siacs.conversations.utils.OnPhoneContactsLoadedListener;
import eu.siacs.conversations.utils.PRNGFixes;
import eu.siacs.conversations.utils.PhoneHelper;
import eu.siacs.conversations.utils.ReplacingSerialSingleThreadExecutor;
import eu.siacs.conversations.utils.SerialSingleThreadExecutor;
import eu.siacs.conversations.utils.Xmlns;
import eu.siacs.conversations.xml.Element;
@ -123,7 +124,7 @@ import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
import eu.siacs.conversations.xmpp.stanzas.PresencePacket;
import me.leolin.shortcutbadger.ShortcutBadger;
public class XmppConnectionService extends Service implements OnPhoneContactsLoadedListener {
public class XmppConnectionService extends Service {
public static final String ACTION_CLEAR_NOTIFICATION = "clear_notification";
public static final String ACTION_DISABLE_FOREGROUND = "disable_foreground";
@ -135,6 +136,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
public static final String ACTION_GCM_MESSAGE_RECEIVED = "gcm_message_received";
private final SerialSingleThreadExecutor mFileAddingExecutor = new SerialSingleThreadExecutor();
private final SerialSingleThreadExecutor mDatabaseExecutor = new SerialSingleThreadExecutor();
private ReplacingSerialSingleThreadExecutor mContactMergerExecutor = new ReplacingSerialSingleThreadExecutor(true);
private final IBinder mBinder = new XmppConnectionBinder();
private final List<Conversation> conversations = new CopyOnWriteArrayList<>();
private final IqGenerator mIqGenerator = new IqGenerator(this);
@ -350,7 +352,6 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
private WakeLock wakeLock;
private PowerManager pm;
private LruCache<String, Bitmap> mBitmapCache;
private Thread mPhoneContactMergerThread;
private EventReceiver mEventReceiver = new EventReceiver();
private boolean mRestoredFromDatabase = false;
@ -1148,21 +1149,59 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
sendIqPacket(account, iqPacket, mDefaultIqHandler);
}
public void onPhoneContactsLoaded(final List<Bundle> phoneContacts) {
if (mPhoneContactMergerThread != null) {
mPhoneContactMergerThread.interrupt();
private void restoreFromDatabase() {
synchronized (this.conversations) {
final Map<String, Account> accountLookupTable = new Hashtable<>();
for (Account account : this.accounts) {
accountLookupTable.put(account.getUuid(), account);
}
mPhoneContactMergerThread = new Thread(new Runnable() {
this.conversations.addAll(databaseBackend.getConversations(Conversation.STATUS_AVAILABLE));
for (Conversation conversation : this.conversations) {
Account account = accountLookupTable.get(conversation.getAccountUuid());
conversation.setAccount(account);
}
Runnable runnable = new Runnable() {
@Override
public void run() {
Log.d(Config.LOGTAG, "restoring roster");
for (Account account : accounts) {
databaseBackend.readRoster(account.getRoster());
account.initAccountServices(XmppConnectionService.this); //roster needs to be loaded at this stage
}
getBitmapCache().evictAll();
loadPhoneContacts();
Log.d(Config.LOGTAG, "restoring messages");
for (Conversation conversation : conversations) {
conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE));
checkDeletedFiles(conversation);
conversation.findUnreadMessages(new Conversation.OnMessageFound() {
@Override
public void onMessageFound(Message message) {
mNotificationService.pushFromBacklog(message);
}
});
}
mNotificationService.finishBacklog(false);
mRestoredFromDatabase = true;
Log.d(Config.LOGTAG, "restored all messages");
updateConversationUi();
}
};
mDatabaseExecutor.execute(runnable);
}
}
public void loadPhoneContacts() {
mContactMergerExecutor.execute(new Runnable() {
@Override
public void run() {
PhoneHelper.loadPhoneContacts(XmppConnectionService.this, new OnPhoneContactsLoadedListener() {
@Override
public void onPhoneContactsLoaded(List<Bundle> phoneContacts) {
Log.d(Config.LOGTAG, "start merging phone contacts with roster");
for (Account account : accounts) {
List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts();
for (Bundle phoneContact : phoneContacts) {
if (Thread.interrupted()) {
Log.d(Config.LOGTAG, "interrupted merging phone contacts");
return;
}
Jid jid;
try {
jid = Jid.fromString(phoneContact.getString("jid"));
@ -1192,57 +1231,9 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
updateAccountUi();
}
});
mPhoneContactMergerThread.start();
}
private void restoreFromDatabase() {
synchronized (this.conversations) {
final Map<String, Account> accountLookupTable = new Hashtable<>();
for (Account account : this.accounts) {
accountLookupTable.put(account.getUuid(), account);
}
this.conversations.addAll(databaseBackend.getConversations(Conversation.STATUS_AVAILABLE));
for (Conversation conversation : this.conversations) {
Account account = accountLookupTable.get(conversation.getAccountUuid());
conversation.setAccount(account);
}
Runnable runnable = new Runnable() {
@Override
public void run() {
Log.d(Config.LOGTAG, "restoring roster");
for (Account account : accounts) {
databaseBackend.readRoster(account.getRoster());
account.initAccountServices(XmppConnectionService.this); //roster needs to be loaded at this stage
}
getBitmapCache().evictAll();
Looper.prepare();
loadPhoneContacts();
Log.d(Config.LOGTAG, "restoring messages");
for (Conversation conversation : conversations) {
conversation.addAll(0, databaseBackend.getMessages(conversation, Config.PAGE_SIZE));
checkDeletedFiles(conversation);
conversation.findUnreadMessages(new Conversation.OnMessageFound() {
@Override
public void onMessageFound(Message message) {
mNotificationService.pushFromBacklog(message);
}
});
}
mNotificationService.finishBacklog(false);
mRestoredFromDatabase = true;
Log.d(Config.LOGTAG, "restored all messages");
updateConversationUi();
}
};
mDatabaseExecutor.execute(runnable);
}
}
public void loadPhoneContacts() {
PhoneHelper.loadPhoneContacts(getApplicationContext(),
new CopyOnWriteArrayList<Bundle>(),
XmppConnectionService.this);
}
public List<Conversation> getConversations() {
return this.conversations;
@ -3120,6 +3111,16 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
return contacts;
}
public Conversation findFirstMuc(Jid jid) {
for(Conversation conversation : getConversations()) {
if (conversation.getJid().toBareJid().equals(jid.toBareJid())
&& conversation.getMode() == Conversation.MODE_MULTI) {
return conversation;
}
}
return null;
}
public NotificationService getNotificationService() {
return this.mNotificationService;
}

View file

@ -13,6 +13,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.text.InputType;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
@ -157,7 +158,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
ConversationFragment.this.conversation.populateWithMessages(ConversationFragment.this.messageList);
updateStatusMessages();
messageListAdapter.notifyDataSetChanged();
int pos = getIndexOf(uuid,messageList);
int pos = Math.max(getIndexOf(uuid,messageList),0);
messagesView.setSelectionFromTop(pos, pxOffset);
messagesLoaded = true;
if (messageLoaderToast != null) {
@ -210,7 +211,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
}
return 0;
return -1;
}
private final int KEYCHAIN_UNLOCK_NOT_REQUIRED = 0;
@ -813,11 +814,13 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
this.messagesLoaded = true;
synchronized (this.messageList) {
final Message first = conversation.getFirstUnreadMessage();
final int bottom = Math.max(0, this.messageList.size() - 1);
final int pos;
if (first == null) {
pos = Math.max(0,this.messageList.size() - 1);
pos = bottom;
} else {
pos = getIndexOf(first.getUuid(), this.messageList);
int i = getIndexOf(first.getUuid(), this.messageList);
pos = i < 0 ? bottom : i;
}
messagesView.setSelection(pos);
}

View file

@ -846,7 +846,16 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
private boolean handleJid(Invite invite) {
List<Contact> contacts = xmppConnectionService.findContacts(invite.getJid());
if (contacts.size() == 0) {
if (invite.isMuc()) {
Conversation muc = xmppConnectionService.findFirstMuc(invite.getJid());
if (muc != null) {
switchToConversation(muc);
return true;
} else {
showJoinConferenceDialog(invite.getJid().toBareJid().toString());
return false;
}
} else if (contacts.size() == 0) {
showCreateContactDialog(invite.getJid().toString(),invite.getFingerprint());
return false;
} else if (contacts.size() == 1) {
@ -1020,13 +1029,13 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
boolean invite() {
if (jid != null) {
if (muc) {
showJoinConferenceDialog(jid);
} else {
return handleJid(this);
}
}
return false;
}
public boolean isMuc() {
return muc;
}
}
}

View file

@ -13,12 +13,14 @@ import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Profile;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.RejectedExecutionException;
public class PhoneHelper {
public static void loadPhoneContacts(Context context, final List<Bundle> phoneContacts, final OnPhoneContactsLoadedListener listener) {
public static void loadPhoneContacts(Context context, final OnPhoneContactsLoadedListener listener) {
final List<Bundle> phoneContacts = new ArrayList<>();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
listener.onPhoneContactsLoaded(phoneContacts);

View file

@ -0,0 +1,14 @@
package eu.siacs.conversations.utils;
public class ReplacingSerialSingleThreadExecutor extends SerialSingleThreadExecutor {
public ReplacingSerialSingleThreadExecutor(boolean prepareLooper) {
super(prepareLooper);
}
@Override
public synchronized void execute(final Runnable r) {
tasks.clear();
super.execute(r);
}
}

View file

@ -1,5 +1,7 @@
package eu.siacs.conversations.utils;
import android.os.Looper;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.Executor;
@ -8,9 +10,24 @@ import java.util.concurrent.Executors;
public class SerialSingleThreadExecutor implements Executor {
final Executor executor = Executors.newSingleThreadExecutor();
final Queue<Runnable> tasks = new ArrayDeque();
protected final Queue<Runnable> tasks = new ArrayDeque();
Runnable active;
public SerialSingleThreadExecutor() {
this(false);
}
public SerialSingleThreadExecutor(boolean prepareLooper) {
if (prepareLooper) {
execute(new Runnable() {
@Override
public void run() {
Looper.prepare();
}
});
}
}
public synchronized void execute(final Runnable r) {
tasks.offer(new Runnable() {
public void run() {

View file

@ -7,6 +7,7 @@ public class XmlHelper {
content = content.replace(">", "&gt;");
content = content.replace("\"", "&quot;");
content = content.replace("'", "&apos;");
content = content.replaceAll("\\p{Cc}", "");
return content;
}
}

View file

@ -47,6 +47,7 @@ public class XmppUri {
// sample : https://conversations.im/i/foo/bar.com
jid = segments.get(1) + "@" + segments.get(2);
}
muc = segments.size() > 1 && "j".equalsIgnoreCase(segments.get(0));
} else if ("xmpp".equalsIgnoreCase(scheme)) {
// sample: xmpp:foo@bar.com
muc = "join".equalsIgnoreCase(uri.getQuery());