From b68851b719d89f2f6b7746189d34ccf5d2f295a6 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Mon, 15 Jul 2019 19:11:00 +0200 Subject: [PATCH] create share button in backup done notification --- .../services/ExportBackupService.java | 134 +++++++++++------- .../ui/adapter/ConversationAdapter.java | 1 + .../ui/adapter/MediaAdapter.java | 3 + .../siacs/conversations/utils/MimeUtils.java | 2 + .../siacs/conversations/utils/UIHelper.java | 5 + .../drawable-hdpi/ic_backup_black_48dp.png | Bin 0 -> 561 bytes .../drawable-hdpi/ic_backup_white_48dp.png | Bin 0 -> 589 bytes .../drawable-mdpi/ic_backup_black_48dp.png | Bin 0 -> 386 bytes .../drawable-mdpi/ic_backup_white_48dp.png | Bin 0 -> 405 bytes .../drawable-xhdpi/ic_backup_black_48dp.png | Bin 0 -> 733 bytes .../drawable-xhdpi/ic_backup_white_48dp.png | Bin 0 -> 770 bytes .../drawable-xxhdpi/ic_backup_black_48dp.png | Bin 0 -> 1116 bytes .../drawable-xxhdpi/ic_backup_white_48dp.png | Bin 0 -> 1177 bytes .../drawable-xxxhdpi/ic_backup_black_48dp.png | Bin 0 -> 1465 bytes .../drawable-xxxhdpi/ic_backup_white_48dp.png | Bin 0 -> 1562 bytes src/main/res/values/attrs.xml | 1 + src/main/res/values/strings.xml | 3 + src/main/res/values/themes.xml | 2 + 18 files changed, 98 insertions(+), 53 deletions(-) create mode 100644 src/main/res/drawable-hdpi/ic_backup_black_48dp.png create mode 100644 src/main/res/drawable-hdpi/ic_backup_white_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_backup_black_48dp.png create mode 100644 src/main/res/drawable-mdpi/ic_backup_white_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_backup_black_48dp.png create mode 100644 src/main/res/drawable-xhdpi/ic_backup_white_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_backup_black_48dp.png create mode 100644 src/main/res/drawable-xxhdpi/ic_backup_white_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_backup_black_48dp.png create mode 100644 src/main/res/drawable-xxxhdpi/ic_backup_white_48dp.png diff --git a/src/main/java/eu/siacs/conversations/services/ExportBackupService.java b/src/main/java/eu/siacs/conversations/services/ExportBackupService.java index d715ea539..7b034a255 100644 --- a/src/main/java/eu/siacs/conversations/services/ExportBackupService.java +++ b/src/main/java/eu/siacs/conversations/services/ExportBackupService.java @@ -21,7 +21,9 @@ import java.io.PrintWriter; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.zip.GZIPOutputStream; @@ -50,6 +52,8 @@ public class ExportBackupService extends Service { public static final String CIPHERMODE = "AES/GCM/NoPadding"; public static final String PROVIDER = "BC"; + public static final String MIME_TYPE = "application/vnd.conversations.backup"; + private static final int NOTIFICATION_ID = 19; private static final int PAGE_SIZE = 20; private static AtomicBoolean running = new AtomicBoolean(false); @@ -213,11 +217,19 @@ public class ExportBackupService extends Service { public int onStartCommand(Intent intent, int flags, int startId) { if (running.compareAndSet(false, true)) { new Thread(() -> { - final boolean success = export(); + boolean success; + List files; + try { + files = export(); + success = true; + } catch (Exception e) { + success = false; + files = Collections.emptyList(); + } stopForeground(true); running.set(false); if (success) { - notifySuccess(); + notifySuccess(files); } stopSelf(); }).start(); @@ -250,81 +262,97 @@ public class ExportBackupService extends Service { } } - private boolean export() { + private List export() throws Exception { NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext(), "backup"); mBuilder.setContentTitle(getString(R.string.notification_create_backup_title)) .setSmallIcon(R.drawable.ic_archive_white_24dp) .setProgress(1, 0, false); startForeground(NOTIFICATION_ID, mBuilder.build()); - try { - int count = 0; - final int max = this.mAccounts.size(); - final SecureRandom secureRandom = new SecureRandom(); - for (Account account : this.mAccounts) { - final byte[] IV = new byte[12]; - final byte[] salt = new byte[16]; - secureRandom.nextBytes(IV); - secureRandom.nextBytes(salt); - final BackupFileHeader backupFileHeader = new BackupFileHeader(getString(R.string.app_name), account.getJid(), System.currentTimeMillis(), IV, salt); - final Progress progress = new Progress(mBuilder, max, count); - final File file = new File(FileBackend.getBackupDirectory(this) + account.getJid().asBareJid().toEscapedString() + ".ceb"); - if (file.getParentFile().mkdirs()) { - Log.d(Config.LOGTAG, "created backup directory " + file.getParentFile().getAbsolutePath()); - } - final FileOutputStream fileOutputStream = new FileOutputStream(file); - final DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream); - backupFileHeader.write(dataOutputStream); - dataOutputStream.flush(); - - final Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER); - byte[] key = getKey(account.getPassword(), salt); - Log.d(Config.LOGTAG, backupFileHeader.toString()); - SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE); - IvParameterSpec ivSpec = new IvParameterSpec(IV); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); - CipherOutputStream cipherOutputStream = new CipherOutputStream(fileOutputStream, cipher); - - GZIPOutputStream gzipOutputStream = new GZIPOutputStream(cipherOutputStream); - PrintWriter writer = new PrintWriter(gzipOutputStream); - SQLiteDatabase db = this.mDatabaseBackend.getReadableDatabase(); - final String uuid = account.getUuid(); - accountExport(db, uuid, writer); - simpleExport(db, Conversation.TABLENAME, Conversation.ACCOUNT, uuid, writer); - messageExport(db, uuid, writer, progress); - for (String table : Arrays.asList(SQLiteAxolotlStore.PREKEY_TABLENAME, SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME, SQLiteAxolotlStore.SESSION_TABLENAME, SQLiteAxolotlStore.IDENTITIES_TABLENAME)) { - simpleExport(db, table, SQLiteAxolotlStore.ACCOUNT, uuid, writer); - } - writer.flush(); - writer.close(); - Log.d(Config.LOGTAG, "written backup to " + file.getAbsoluteFile()); - count++; + int count = 0; + final int max = this.mAccounts.size(); + final SecureRandom secureRandom = new SecureRandom(); + final List files = new ArrayList<>(); + for (Account account : this.mAccounts) { + final byte[] IV = new byte[12]; + final byte[] salt = new byte[16]; + secureRandom.nextBytes(IV); + secureRandom.nextBytes(salt); + final BackupFileHeader backupFileHeader = new BackupFileHeader(getString(R.string.app_name), account.getJid(), System.currentTimeMillis(), IV, salt); + final Progress progress = new Progress(mBuilder, max, count); + final File file = new File(FileBackend.getBackupDirectory(this) + account.getJid().asBareJid().toEscapedString() + ".ceb"); + files.add(file); + if (file.getParentFile().mkdirs()) { + Log.d(Config.LOGTAG, "created backup directory " + file.getParentFile().getAbsolutePath()); } - return true; - } catch (Exception e) { - Log.d(Config.LOGTAG, "unable to create backup ", e); - return false; + final FileOutputStream fileOutputStream = new FileOutputStream(file); + final DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream); + backupFileHeader.write(dataOutputStream); + dataOutputStream.flush(); + + final Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER); + byte[] key = getKey(account.getPassword(), salt); + Log.d(Config.LOGTAG, backupFileHeader.toString()); + SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE); + IvParameterSpec ivSpec = new IvParameterSpec(IV); + cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec); + CipherOutputStream cipherOutputStream = new CipherOutputStream(fileOutputStream, cipher); + + GZIPOutputStream gzipOutputStream = new GZIPOutputStream(cipherOutputStream); + PrintWriter writer = new PrintWriter(gzipOutputStream); + SQLiteDatabase db = this.mDatabaseBackend.getReadableDatabase(); + final String uuid = account.getUuid(); + accountExport(db, uuid, writer); + simpleExport(db, Conversation.TABLENAME, Conversation.ACCOUNT, uuid, writer); + messageExport(db, uuid, writer, progress); + for (String table : Arrays.asList(SQLiteAxolotlStore.PREKEY_TABLENAME, SQLiteAxolotlStore.SIGNED_PREKEY_TABLENAME, SQLiteAxolotlStore.SESSION_TABLENAME, SQLiteAxolotlStore.IDENTITIES_TABLENAME)) { + simpleExport(db, table, SQLiteAxolotlStore.ACCOUNT, uuid, writer); + } + writer.flush(); + writer.close(); + Log.d(Config.LOGTAG, "written backup to " + file.getAbsoluteFile()); + count++; } + return files; } - private void notifySuccess() { + private void notifySuccess(List files) { final String path = FileBackend.getBackupDirectory(this); - PendingIntent pendingIntent = null; + PendingIntent openFolderIntent = null; for (Intent intent : getPossibleFileOpenIntents(this, path)) { if (intent.resolveActivityInfo(getPackageManager(), 0) != null) { - pendingIntent = PendingIntent.getActivity(this, 189, intent, PendingIntent.FLAG_UPDATE_CURRENT); + openFolderIntent = PendingIntent.getActivity(this, 189, intent, PendingIntent.FLAG_UPDATE_CURRENT); break; } } + PendingIntent shareFilesIntent = null; + if (files.size() > 0) { + final Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE); + ArrayList uris = new ArrayList<>(); + for(File file : files) { + uris.add(FileBackend.getUriForFile(this, file)); + } + intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + intent.setType(MIME_TYPE); + final Intent chooser = Intent.createChooser(intent, getString(R.string.share_backup_files)); + shareFilesIntent = PendingIntent.getActivity(this,190, chooser, PendingIntent.FLAG_UPDATE_CURRENT); + } + NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext(), "backup"); mBuilder.setContentTitle(getString(R.string.notification_backup_created_title)) .setContentText(getString(R.string.notification_backup_created_subtitle, path)) .setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.notification_backup_created_subtitle, FileBackend.getBackupDirectory(this)))) .setAutoCancel(true) - .setContentIntent(pendingIntent) + .setContentIntent(openFolderIntent) .setSmallIcon(R.drawable.ic_archive_white_24dp); + + if (shareFilesIntent != null) { + mBuilder.addAction(R.drawable.ic_share_white_24dp, getString(R.string.share_backup_files), shareFilesIntent); + } + notificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index ad5ddce89..3ea451653 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -94,6 +94,7 @@ public class ConversationAdapter extends RecyclerView.Adapterdc5cH-b0=D=O1`+&;6cz{l^s*6%`c~ZPDYR2j2K$*^=*G z8+XBeo7K2x2aQ`4R$1AYUX5x}qkiv&h`n=c{ZYHU5X5iBF6&mwSC@(( zQ04C0AaR>a2pRTBYuc-NC}iAy&60IpNU$ps)h8s{0SVgbTQbms4w)Mf5^h-4?Qp`V z8NY;x4H^_8wq&O@*QC#s5I=(uNxEu{b$KOJ!HFgPv{7_zMue(4v82Ny+h#f=Cyq24 zd)~7NI5DJ;B5L(45hsQ;Ys@)&G$eT2L~!CS?yXZ=RHiF2C!Q31&{gr?$#Cc?NWpm} zD>|B$lYn$%CFx0aP6E;;fX+0W1f(9|WExHa(kJb3I~6AZ=?pv*BpU@ zZWeO|8p<1JGH;LUGc&mYmARES(D7V>=IPAamzu}%~aPY;Jx!nt**mE;azb zwH$Efv;)xMY287+{;0#tx^gb7sKZpcNMDmi4LCYS{S z+C{cqzni9gQBKS#n>T4lwPNf literal 0 HcmV?d00001 diff --git a/src/main/res/drawable-hdpi/ic_backup_white_48dp.png b/src/main/res/drawable-hdpi/ic_backup_white_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..3ff57ad3e897a332dc77086a5d3fdb9ed0c40b41 GIT binary patch literal 589 zcmV-T0Bp}VWfd*+9a9l|5T|oUj(Q*`|2D6-HH+>yJ`n#hb#l7Yv#lL|nHXH>B-ck7z zl-E6UGZLI5A_j59nxi0HBZ@(f>^Tb3#owSIdybMc@(XlA$+0JWpo9oF)f{`$X+(I6 zzD@vbO$x$ik3cXita=5S@C~%!+mU?~>Ry3b!VTX*$Gifq2t&SIYT=<@&t5p}*9W5z z(eUQ0BQFTTUi@f0{*ix$>|3T3gNi&R>#9f$63RR$%O=K5T(~PiE~6R#|+6jGNjAsVV3UDffiFJSYVqwI>wnQRm9*9e~=>} zLK3V37!xhh$ye_oiut6(B1Se5^}IPz!$4U*pPUGJ%cR-It_$ScO9rW4K!e$ z$n7J;mD_I$S$c>Qn`8iB%~7DpHyaM-5Bb3=A0wTwF;0v*E{R5T`yvLiY;nsAq1A9m ggMbnlJRZ*gUuq}bb_}IlRR91007*qoM6N<$f_R^x2LJ#7 literal 0 HcmV?d00001 diff --git a/src/main/res/drawable-mdpi/ic_backup_white_48dp.png b/src/main/res/drawable-mdpi/ic_backup_white_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..a9602d11b8d4e33f91367f9676eebce86d88c117 GIT binary patch literal 405 zcmV;G0c!qYU6oB!gw#7w6AHZ6C8lfO9C{)|G5Tytb2Nyx8_-E0{MU0E9)CbTPaFR+9g|>FG zON!-l$YQ|cp2S{o$amIoesFUk5nX9%X-u=i8ISb%Vn~+#XgXyo36S9yZ8t$e2V4-Rlej>QxUI$k=IIl+4l^2Hi5>3g5tf5P zSi2^mfXj%e90Um^I%K1O8Urw|k0h4Efi2LiHxP|5psHJMBs`wDq(mkN6x4@fCj6c$ z{sdh0dOZOLO!z=Sb8`|Ahdxj@uTM;r5TR*YpPXou72eS$!9iC=7+M8f+rW$PW)<*+ zrfr~Z6=(^IjO@N-;o9ys74i(QQ=6P12pia`j0pa0GX9Q&pUibW8D|Y9gMhHW6{9ho zeL3v6CC@f@yyB50j}|T!a!3%cI4O_<{D0sZ6}?4(_}0Fh00000NkvXXu0mjfY7nTZ literal 0 HcmV?d00001 diff --git a/src/main/res/drawable-xhdpi/ic_backup_black_48dp.png b/src/main/res/drawable-xhdpi/ic_backup_black_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..248289e97e9b984f3c8441d9690d26fe75659755 GIT binary patch literal 733 zcmV<30wVp1P)Ds^(9wc2%hE=pP1M4*1VKb(xCjD8NL;uJ0+HyG*-S8?s}|OXZmMl0iiL}U z0ud~Vp$}tP)*^8cGL_Oep)$_fPBcH~o^$5j1LyZ&3-5ECnTz8%j^j9v<2a5s6Vw`6$0d|yIyd{Thu^bazqmIC7;yKI64wvH@jReLyl8A@B;S9d3 z<0+!BA!_hZ2Xlzxe$$38%6W)rT0dnJ*?uMvjT@taB09tuMDr#&SiGm7LJaH!6_`gk z6NsUWQ;Knq5Q9r#SO;QwmoVrEbH)SGRAbC2g82<%NF!3DokFWRI_PJNS)|~_iF^2~ z*ZN*qH~ENoUL3$v!f74PeSp7+^7-BpMo?159p(}B^F1fzsKK*(CJ{a7DRE<87cvwUG01y6M6xlPvv}H6Beiec!g-)c0}X4 z0lrxr@SPCMS{xvpge9v3qP7Q&z%Q!VQQ^*dEYsbwC;p+x{hn_Z9~X z16;NHMFv%5tqo`ZfcusPOc4TrTIQ_`=wU?^v2F`QSP|y4bpd^>ae@qD(PpURKP@a< z6wt~BuGsqVS(RYLe_@moHr33Zz@NXHEgfev&>x->wiV_!^MU;3X=TSE^pXwKYb!w| z1*)QpBzeT=P0>RH&#GzT9xwPxnnk2YTO>`2VWKn;VjahE9LI4S$8ns0bEkQc(oxfv P00000NkvXXu0mjf7#&5* literal 0 HcmV?d00001 diff --git a/src/main/res/drawable-xhdpi/ic_backup_white_48dp.png b/src/main/res/drawable-xhdpi/ic_backup_white_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..2180f73e8d7d300cddc7ae2c2a071ee58ddd4260 GIT binary patch literal 770 zcmV+d1O5DoP) z8s{2&w+58)!OVOi0;Gttdvidqnfamwn4@K5K-kdNmONpNK0^NjMg-jC>n z3(S`!j1lqzt_sYTCfxP{VgmE!3FrO*8bs#H6Bek-0Xl@{%M%82fFYsz@`McaD8&nm zw(V4t^`R7BECzffq)1u}fMbdks{uW>111#Ttp>#H{t(0eisx1XmKB4x13Ih*Boqg1 z{}3zQS_~LhC@$OmMW(1BZ7rZFchkF;0_F(iZrZ?-m4N=g54L)+uMA=Dqs5Qd*3kNg zyGKc3P2PX%y=OD4*i+j^2OO7d`t|Vwyo6PP-y|iQ0TiwL4E+3ETOYF?VV2-FM9KCC z-DTWliQu(B+sgz2{2y@T40?tFU^V~%rO?&kWQ>vx^&`}+I`Z}@Rt7r($QF)q-}cf7{|8mOj_*eRrj19b2& zvVcu+niQKTAO;H9%DW6AOIRPr*+L$>iM@0q%iM1?v6{TIhQmxE0d0~uxtYANiZ}QN z33!)Dv6?*4z(qu9gX|#E*6|ghyf3(gh^l8C(H|2$LgbWi0?FatrkDt+;4G5kouz_^ zxPu-fg#F2_L_jr{kdW5TJvi=ehL8|9%w0HaJ%1x1?;^M1s3d?IHCb@boDr(oPNa7U7(E6y@oivR|rWF z8`;GX+L%HDT#6JD;3i0tV{6$%8bcmcOrIBx#K@hz>fhQWJ9DUrteg+Uk zJC8!5-6$(!4`Yaa9;HNopsJ4FkzD3cNVE|p367D;bsmL8M^JGmKO?!%qmZbN0s>dd zXy|zWQf?lyr$~pFMY&MY9AouG*iVQHM^TfA(4>b!^IrAtz_KJqmW2QbCfa` zpqOs=^Qa^edf38sJ@0-V#Y8jg$JdRFxSvNgk?;`-JiQvJJX(pqri`pg=-1B^iA0^O zB#S5Y^F$`m#}qIh-|FXyP@;p(Q>lMb5vfEO9_AX)>F0@9q5&$Hqg_8wB>*HCut0t{ z8}O0^%CaVAtzyIi&0CrzbL_Q1{(nqR#4m_#&hBTP2N2urI>_RU=ln*J6Dms zSejO9P*BOUv@(W7c2jiFL=shn+(#pa_>`aMWytZ@%4vq^rHdB!QAdJn7-Nhv#u#Ia iF~%5Uj4{R-WBvo3>(GofhKo-C0000& zMxDi~6k)=!I+;?Z7Ym|nOt((Q@UEK(3Zht*YGGn5vJON+=Fe&=gKlkIn>J}dn{3JB zMJVlN&RKt)Z_b4OC+M z8-pKHNfY~t@h^)h$tj|2rlK5xD%i%mjIo@CImXsf2D*X046xFEqn)*-2eghu%-~fs zyvdEF1GI)W_y@0>Cd%4U0BYp|wi;t+aRaUAD{S`#Hy0~V3keEQl81{AsG8#xvbPBo z6HtUR6uL7+iUsI42JxdmxuqC@8n}pGjc}KApgS4I&nCD-GSEi;#_uk0t5l#ce<7hk z)=31ap&u#rQ6&%PIFdRl4QMCQdQ1|~dXh+Mk~%p+Um~$?DL}1AtwjP*h!LcAo?8Eb zUPE%P_ytr&BfB_E53_h#lqg=7BwT2qo7h7S)7U7A!FWt`uy8;%wDAoY0E;|c6HO8- z1kiQtV-&zPj|HOLwt=eH!xY%(u|)KTU7%)uheGmLAZoM)6yzvbpLo0^I&25%c76sQ zdAuVUrowxm?M(W`V}YpAYoMn{`^RH}sKZ;JHnM*5SRm^066gss{_J$)&~`5Q z&trk;H1G2|Eo@jB&_?32cq}~h$2h@51eXI8$)AFv!+x13fRF$0AXNeeOWl6PM3pl?Xl}=nV9#JRTp2 zzNR)mP&FeGcmxpju{s~nlLC085PeL=|AD?0z$1s~z|}x?WCZZYAE%BY;OH(dHb`TlkY%;uOA5azLLc zkVBUUV+>~%$g$lR!>|H57Q+~(6v(kzf`+sLxpcn*x%aXmu0SrGFq~5$mrmSEQp)f&t|`za1#)TJu!@8NIW}Z4e6B!_^}D~7SD>!k{!T`L9O}sZ_$dW) z=z+QKS`{c?v#g%`HgOb(^dDxqc}aot)IJZihPVPglzThe7wR4*Lpj%Z?Ul@3 zWlYpd;MzcjM@UhQeNSldYvGA9(ymnn_Xbkk(x$XgxH(#;gb+bl8K z3EMprSjj!Kaga~>i6O>GA-NRe4AD;)9W)d4@I;r65-5-YDUbpwkOC=?0_iA_0x6IJ rDUbpwkOJu_kOC=?0x6IJmBjo9--gpSw0n+n00000NkvXXu0mjf(p?MD literal 0 HcmV?d00001 diff --git a/src/main/res/drawable-xxxhdpi/ic_backup_black_48dp.png b/src/main/res/drawable-xxxhdpi/ic_backup_black_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..33d75230cfe7189fb64a79fb64bcbfa66a2ba60c GIT binary patch literal 1465 zcmV;q1xEUbP)G0000GmNklqr?$l|U;qFB00000000000HL#MFTYV0Y#hhGLuqMvr6nyjP(Xu;nsj4O zDdA!u1p1QNN)ZVJL_nEntP(dajGHmCQGp2P0ul&OOrXGmU?Mj!1Oy_N+5%AnHZ3I) zEoG=6IBhwPo02r8lul>nJm>O!KmWn=Tg;i0lgAXIe8?8|bCxFl;s%|x6X!C&ahh-0 z%=;{)lme`@mBq8X%N`n$Bs8#%YQ~erfU^pDl|5WXQgDM^EFuppsfH2dARS1WB>0Bc zcnGT>jb|e_kPP^n&nUs_qjHWS8TLJMuBc4UXU-3St1RPB0S>6`_K?v?EGlbT1aJzhv1g<2<4$2H^Sx z4o{%oAfhxQ`sY`f;B%ClMlIrn^D9kolmDUC!_*+&IKScq3s9<(KfQ8()d_Z^&`>ra zUOB(=1h*N6%Z;VZL+96@U@@*Xfj>NTe*Fn{;9~Q*<+1bYPjCg-T1ck{&#ynhlep4+ zkDgzDf+#LDmky7fUw?vaWW0&o_U!rfCun0kA5+cqj3OhA@y(Nu{zGXKHN3@G(%4W= z`}h26ujx+mUb<%39Dws{Odxc!i)o}-WdP2vG(neB%woWe;7S0_uRVcqkf#|?H32!l z{sedUgj|wrMu5(*KY{QolSraL)CTPQ`V(~U4*hOf0MD;Kfv}Za`q2dj0bUdV+e2=%ZQs=MVe@$I0cs?bSbj2qvf@La!C*f8!aF30Bc- zEA-DFk_jAU&`XE(&mWozE>l2{M$oB${t!*DgC5P(KYz$3m;v2er+@yCO;Ar3-8y6E zcYT64;cj`{vGcn=!6mZkYKqGFZGu zB^%%u8$eAtK(h^?W-UP622gVbpxp*gbBEzJfUYuVwE+~p4NW$Hq787)22ivQj@tl= z&caR`KvAQ;jMH@$me>G_5>Se0vH|jNYydSa0QEM2ng)PRZ2&cO0CQ{rHTwbb>9hfq ztOtN2Hh_|90C?R7P%;w$hV!otpunM!u6Ei03TokQ6*ho^HE_2G=WPJjmD8=4Z2*_W z$)#Ia{B8rdY7;$*+5oP4jvfuB-Ue{Z1tQ$jR2;;(B1*4qMT`rY$)VSZxQ1k$S;>8y zi)5I&KrVf>9?2*(n?B3oB$6>^HxKMFt|A#>S{Xw>n#fJWWI!eTY&PwPNwYO1(PA9L zq|srrA-M_K5tAnMG=JSter&p1fvIMlL+a)y9@!+3^8e86^& zQbz+VB#?kf&_V-s>}NgI%%qU6{%a2o1ONa400jA44{~({000000000000004q?P3I T@}!)D00000NkvXXu0mjfg^!Rs literal 0 HcmV?d00001 diff --git a/src/main/res/drawable-xxxhdpi/ic_backup_white_48dp.png b/src/main/res/drawable-xxxhdpi/ic_backup_white_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..19e40517da00c23651574c1f37341012acf09568 GIT binary patch literal 1562 zcmZuxc{J2}6#xFl*v5<{BWq(wA!TMFjjb6{7>z-^vOUuaDOt1T$qywmO+t0-V@k`z zvujghD6&N;Noh*fh02oIHJ2x>m z|4JF87*}53VgVre$@zjk!b!1~HBuctulvY9#N5Qy^l;bySG2SJsZ$wO89P+MW|C8M12~7Z(``qix8~DE zE9hmmngz^%AOn6ftU${&lw#zOx54ZcZJd+3Z~nMI>p$I;zb&iswu;MoZa(X^Ch z9)pdz6|+A*GRv&rqp&KzNLmG-r`aVHDma+*UHt&6Z{%7e_Wl|>54Et7>B2W`n$g>a z>JwcuXAdRzBGD+Sj-LQOa0GjP3!WyI?Hk}42jM2bxhcitEi%N5n}u$yOW}}z?Pgv> zcJeVujZYH3RbZhds7jcX1}CiK7AA@$^f4JrMZ4H&@nSP;Ify0)BeTJ_Sv(?Fx&8X* zTqK5xia0$JwjC+UNmpxB8SCHx^c|e$V>=r~P)km(Oms>Uf#8~l*BT|7SaUrM>H;ON z>L*`W^{N736I4|RoMdToAxMKS7BEkh380r0XQy7NaEr7K8A4Q`a+kG zi+rpHr0O8yZXS^zk`{*{=4)v85E#|X-f)EQTlwm^Y-55fvA}y@fnTxUQY=^sTK*(l zL^9$ei0vt>0W#d*K{vODy(%fw_()-4=lzg8KbUhN=!x>1&{}l#2 z_=SG3K)xiqXh-v);3a_yc*K1wFytQoz5et*5czBn;z63G7i(lfGE>L^8 zEPZs7a8**)`D!c$ekbT9&|I8s!oWZ(g-7N`)Xrn7^`n-Y6y22^(OLQ;&E7u63I}wx zX`y&K@*z4h+@M0Ne70BVHxu8rTJiw@XECU2wHAxP4MYWIS%^S3_(w^TZ!RS`FTC-E zwZ2V>Pw%5!C&%QzB-k#TQf<~17EMpCHq`k7BP{i9M-dni6Q&60iz#q7DXm0>TH(ej zb%maJT_!!lQY%c<_Ln2lqc4`C@ZK4vo)9vjy^jM@D)$y17SC5_8^O#I7)va*`mE?g z;prn7ITdR4gHp9uSiH17^z2l&$hRIbsE!U6TWO>oyNyV1_{e-w<_n$oIx+QND+=#k zRysE70!nX3CoXSjODew5`PdgP_T!vll`eIP*&`OxEwtAYdD4cSZ~;zr>tjo*6weU8 z6EeG6!@i4%dw0efl5#5t#nH(Q4A82lWg2#A`?~+|W>dl`JtGno8VaX`3_qcGo6FrF zFwRO01FaVC=>^Ht7<^_<5YAe{-y!Nsq)KdmzWTNIlV8I=AM}c^RUmhBRCax+q>anw zNRor5XNh_DK$K!Vx2)VN@^DhyOnfM}?B-e2+RrR+5(q}h&#lQX377Gce_g@NwJ~nGTeOJzbaG-zXM{|{M4Kw<2R%Q@Wo!JbW7BS5{kSoC z`UjGs?*b={+)ULGzh&5F{Y}o>IyoIkMiB!s{spSmuFe1e literal 0 HcmV?d00001 diff --git a/src/main/res/values/attrs.xml b/src/main/res/values/attrs.xml index 2c2acba97..e2f7ddf76 100644 --- a/src/main/res/values/attrs.xml +++ b/src/main/res/values/attrs.xml @@ -63,6 +63,7 @@ + diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 419928a80..90866434e 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -868,4 +868,7 @@ This looks like a domain address Add anyway This looks like a channel address + Share backup files + Conversations backup + Event diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml index e7bc3cd31..f4c870603 100644 --- a/src/main/res/values/themes.xml +++ b/src/main/res/values/themes.xml @@ -74,6 +74,7 @@ @drawable/ic_event_black_48dp @drawable/ic_archive_black_48dp @drawable/ic_book_black_48dp + @drawable/ic_backup_black_48dp @drawable/ic_help_black_48dp @drawable/ic_group_add_white_24dp @@ -187,6 +188,7 @@ @drawable/ic_event_white_48dp @drawable/ic_archive_white_48dp @drawable/ic_book_white_48dp + @drawable/ic_backup_white_48dp @drawable/ic_help_white_48dp @drawable/ic_group_add_white_24dp