diff --git a/.circleci/config.yml b/.circleci/config.yml index d524fe69baadd7f3cb6034f3ad979569a0adc5a9..e824e3facec432c93ac6752d3da2a8ffe9903d92 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,7 +4,7 @@ jobs: build: working_directory: ~/code docker: - - image: circleci/android:api-29 + - image: cimg/android:2022.12.1 steps: - checkout - restore_cache: @@ -36,7 +36,7 @@ jobs: test: working_directory: ~/code docker: - - image: circleci/android:api-29 + - image: cimg/android:2022.12.1 steps: - checkout - restore_cache: diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6efec05db00131d3f7e0c3100a32ddfe5e22c3b7..a8cbba534f501070ee9c0981b8a31887b735feca 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: "registry.gitlab.e.foundation/e/os/docker-android-apps-cicd:legacy" +image: "registry.gitlab.e.foundation/e/os/docker-android-apps-cicd:0-java11" stages: - update-from-upstream diff --git a/android-smsmms/build.gradle b/android-smsmms/build.gradle index fd0c7c194cc50c7622efcf836f9f457d419a5b34..0c14ab9b4f3cc0f96629edb07bbff364a57755d9 100644 --- a/android-smsmms/build.gradle +++ b/android-smsmms/build.gradle @@ -23,15 +23,16 @@ android { compileSdkVersion 25 defaultConfig { - minSdkVersion 21 + minSdkVersion 23 targetSdkVersion 25 } - lintOptions { - abortOnError false - } useLibrary 'org.apache.http.legacy' + lint { + abortOnError false + } + namespace 'com.klinker.android.send_message' } dependencies { diff --git a/android-smsmms/src/main/AndroidManifest.xml b/android-smsmms/src/main/AndroidManifest.xml index c87baa9a5a11c91f95b2c5592412ba19becfe55b..3af6653c90e94bf4a7aa35349c9a1dd3c6ee6042 100755 --- a/android-smsmms/src/main/AndroidManifest.xml +++ b/android-smsmms/src/main/AndroidManifest.xml @@ -1,7 +1,5 @@ - + diff --git a/android-smsmms/src/main/java/com/android/mms/service_alt/ApnSettings.java b/android-smsmms/src/main/java/com/android/mms/service_alt/ApnSettings.java deleted file mode 100755 index cf36a4043cbe77b6f315c5191e5bacc23e4702b3..0000000000000000000000000000000000000000 --- a/android-smsmms/src/main/java/com/android/mms/service_alt/ApnSettings.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (C) 2015 Jacob Klinker - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.mms.service_alt; - -import android.content.Context; -import android.content.SharedPreferences; -import android.database.Cursor; -import android.database.sqlite.SqliteWrapper; -import android.net.NetworkUtilsHelper; -import android.net.Uri; -import android.preference.PreferenceManager; -import android.provider.Telephony; -import android.text.TextUtils; -import com.android.mms.service_alt.exception.ApnException; -import timber.log.Timber; - -import java.net.URI; -import java.net.URISyntaxException; - -/** - * APN settings used for MMS transactions - */ -public class ApnSettings { - - // MMSC URL - private final String mServiceCenter; - // MMSC proxy address - private final String mProxyAddress; - // MMSC proxy port - private final int mProxyPort; - // Debug text for this APN: a concatenation of interesting columns of this APN - private final String mDebugText; - - private static final String[] APN_PROJECTION = { - Telephony.Carriers.TYPE, - Telephony.Carriers.MMSC, - Telephony.Carriers.MMSPROXY, - Telephony.Carriers.MMSPORT, - Telephony.Carriers.NAME, - Telephony.Carriers.APN, - Telephony.Carriers.BEARER, - Telephony.Carriers.PROTOCOL, - Telephony.Carriers.ROAMING_PROTOCOL, - Telephony.Carriers.AUTH_TYPE, - Telephony.Carriers.MVNO_TYPE, - Telephony.Carriers.MVNO_MATCH_DATA, - Telephony.Carriers.PROXY, - Telephony.Carriers.PORT, - Telephony.Carriers.SERVER, - Telephony.Carriers.USER, - Telephony.Carriers.PASSWORD, - }; - private static final int COLUMN_TYPE = 0; - private static final int COLUMN_MMSC = 1; - private static final int COLUMN_MMSPROXY = 2; - private static final int COLUMN_MMSPORT = 3; - private static final int COLUMN_NAME = 4; - private static final int COLUMN_APN = 5; - private static final int COLUMN_BEARER = 6; - private static final int COLUMN_PROTOCOL = 7; - private static final int COLUMN_ROAMING_PROTOCOL = 8; - private static final int COLUMN_AUTH_TYPE = 9; - private static final int COLUMN_MVNO_TYPE = 10; - private static final int COLUMN_MVNO_MATCH_DATA = 11; - private static final int COLUMN_PROXY = 12; - private static final int COLUMN_PORT = 13; - private static final int COLUMN_SERVER = 14; - private static final int COLUMN_USER = 15; - private static final int COLUMN_PASSWORD = 16; - - - /** - * Load APN settings from system - * - * @param context - * @param apnName the optional APN name to match - */ - public static ApnSettings load(Context context, String apnName, int subId) - throws ApnException { - SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); - String mmsc = sharedPrefs.getString("mmsc_url", ""); - if (!TextUtils.isEmpty(mmsc)) { - String mmsProxy = sharedPrefs.getString("mms_proxy", ""); - String mmsPort = sharedPrefs.getString("mms_port", ""); - return new ApnSettings(mmsc, mmsProxy, parsePort(mmsPort), "Default from settings"); - } - - Timber.v("ApnSettings: apnName " + apnName); - // TODO: CURRENT semantics is currently broken in telephony. Revive this when it is fixed. - //String selection = Telephony.Carriers.CURRENT + " IS NOT NULL"; - String selection = null; - String[] selectionArgs = null; - apnName = apnName != null ? apnName.trim() : null; - if (!TextUtils.isEmpty(apnName)) { - //selection += " AND " + Telephony.Carriers.APN + "=?"; - selection = Telephony.Carriers.APN + "=?"; - selectionArgs = new String[]{ apnName }; - } - Cursor cursor = null; - try { - cursor = SqliteWrapper.query( - context, - context.getContentResolver(), - Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "/subId/" + subId), - APN_PROJECTION, - selection, - selectionArgs, - null/*sortOrder*/); - if (cursor != null) { - String mmscUrl = null; - String proxyAddress = null; - int proxyPort = -1; - while (cursor.moveToNext()) { - // Read values from APN settings - if (isValidApnType( - cursor.getString(COLUMN_TYPE), "mms")) { - mmscUrl = trimWithNullCheck(cursor.getString(COLUMN_MMSC)); - if (TextUtils.isEmpty(mmscUrl)) { - continue; - } - mmscUrl = NetworkUtilsHelper.trimV4AddrZeros(mmscUrl); - try { - new URI(mmscUrl); - } catch (URISyntaxException e) { - throw new ApnException("Invalid MMSC url " + mmscUrl); - } - proxyAddress = trimWithNullCheck(cursor.getString(COLUMN_MMSPROXY)); - if (!TextUtils.isEmpty(proxyAddress)) { - proxyAddress = NetworkUtilsHelper.trimV4AddrZeros(proxyAddress); - final String portString = - trimWithNullCheck(cursor.getString(COLUMN_MMSPORT)); - if (portString != null) { - try { - proxyPort = Integer.parseInt(portString); - } catch (NumberFormatException e) { - Timber.e("Invalid port " + portString); - throw new ApnException("Invalid port " + portString); - } - } - } - return new ApnSettings( - mmscUrl, proxyAddress, proxyPort, getDebugText(cursor)); - } - } - - } - } finally { - if (cursor != null) { - cursor.close(); - } - } - - return new ApnSettings("", "", 80, "Failed to find APNs :("); - } - - private static String getDebugText(Cursor cursor) { - final StringBuilder sb = new StringBuilder(); - sb.append("APN ["); - for (int i = 0; i < cursor.getColumnCount(); i++) { - final String name = cursor.getColumnName(i); - final String value = cursor.getString(i); - if (TextUtils.isEmpty(value)) { - continue; - } - if (i > 0) { - sb.append(' '); - } - sb.append(name).append('=').append(value); - } - sb.append("]"); - return sb.toString(); - } - - private static String trimWithNullCheck(String value) { - return value != null ? value.trim() : null; - } - - public ApnSettings(String mmscUrl, String proxyAddr, int proxyPort, String debugText) { - mServiceCenter = mmscUrl; - mProxyAddress = proxyAddr; - mProxyPort = proxyPort; - mDebugText = debugText; - } - - public String getMmscUrl() { - return mServiceCenter; - } - - public String getProxyAddress() { - return mProxyAddress; - } - - public int getProxyPort() { - return mProxyPort; - } - - public boolean isProxySet() { - return !TextUtils.isEmpty(mProxyAddress); - } - - private static boolean isValidApnType(String types, String requestType) { - // If APN type is unspecified, assume APN_TYPE_ALL. - if (TextUtils.isEmpty(types)) { - return true; - } - for (String type : types.split(",")) { - type = type.trim(); - if (type.equals(requestType) || type.equals("*")) { - return true; - } - } - return false; - } - - private static int parsePort(String port) { - if (TextUtils.isEmpty(port)) { - return 80; - } else { - return Integer.parseInt(port); - } - } - - public String toString() { - return mDebugText; - } -} diff --git a/android-smsmms/src/main/java/com/android/mms/service_alt/DownloadRequest.java b/android-smsmms/src/main/java/com/android/mms/service_alt/DownloadRequest.java index b706794975ee631f9d38c65764981a7665086379..4a4cd749765a3d176c493f879d0370bba56bdb2a 100755 --- a/android-smsmms/src/main/java/com/android/mms/service_alt/DownloadRequest.java +++ b/android-smsmms/src/main/java/com/android/mms/service_alt/DownloadRequest.java @@ -28,7 +28,6 @@ import android.os.Bundle; import android.provider.Telephony; import android.text.TextUtils; -import com.android.mms.service_alt.exception.MmsHttpException; import com.google.android.mms.MmsException; import com.google.android.mms.pdu_alt.GenericPdu; import com.google.android.mms.pdu_alt.PduHeaders; @@ -75,44 +74,6 @@ public class DownloadRequest extends MmsRequest { mContentUri = contentUri; } - @Override - protected byte[] doHttp(Context context, MmsNetworkManager netMgr, ApnSettings apn) - throws MmsHttpException { - final MmsHttpClient mmsHttpClient = netMgr.getOrCreateHttpClient(); - if (mmsHttpClient == null) { - Timber.e("MMS network is not ready!"); - throw new MmsHttpException(0/*statusCode*/, "MMS network is not ready"); - } - return mmsHttpClient.execute( - mLocationUrl, - null/*pud*/, - MmsHttpClient.METHOD_GET, - apn.isProxySet(), - apn.getProxyAddress(), - apn.getProxyPort(), - mMmsConfig); - } - - @Override - protected PendingIntent getPendingIntent() { - return mDownloadedIntent; - } - - @Override - protected int getQueueType() { - return 1; - } - - @Override - protected Uri persistIfRequired(Context context, int result, byte[] response) { - if (!mRequestManager.getAutoPersistingPref()) { - notifyOfDownload(context); - return null; - } - - return persist(context, response, mMmsConfig, mLocationUrl, mSubId, mCreator); - } - public static Uri persist(Context context, byte[] response, MmsConfig.Overridden mmsConfig, String locationUrl, int subId, String creator) { // Let any mms apps running as secondary user know that a new mms has been downloaded. @@ -266,41 +227,6 @@ public class DownloadRequest extends MmsRequest { // } } - /** - * Transfer the received response to the caller (for download requests write to content uri) - * - * @param fillIn the intent that will be returned to the caller - * @param response the pdu to transfer - */ - @Override - protected boolean transferResponse(Intent fillIn, final byte[] response) { - return mRequestManager.writePduToContentUri(mContentUri, response); - } - - @Override - protected boolean prepareForHttpRequest() { - return true; - } - - /** - * Try downloading via the carrier app. - * - * @param context The context - * @param carrierMessagingServicePackage The carrier messaging service handling the download - */ - public void tryDownloadingByCarrierApp(Context context, String carrierMessagingServicePackage) { -// final CarrierDownloadManager carrierDownloadManger = new CarrierDownloadManager(); -// final CarrierDownloadCompleteCallback downloadCallback = -// new CarrierDownloadCompleteCallback(context, carrierDownloadManger); -// carrierDownloadManger.downloadMms(context, carrierMessagingServicePackage, -// downloadCallback); - } - - @Override - protected void revokeUriPermission(Context context) { - context.revokeUriPermission(mContentUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); - } - private String getContentLocation(Context context, Uri uri) throws MmsException { Cursor cursor = android.database.sqlite.SqliteWrapper.query(context, context.getContentResolver(), diff --git a/android-smsmms/src/main/java/com/android/mms/service_alt/MmsConfig.java b/android-smsmms/src/main/java/com/android/mms/service_alt/MmsConfig.java index 00eb2357a3710662cdcfde3c8019b3daf0499646..597826ac2b062caac718fc5f079292f46986e76a 100755 --- a/android-smsmms/src/main/java/com/android/mms/service_alt/MmsConfig.java +++ b/android-smsmms/src/main/java/com/android/mms/service_alt/MmsConfig.java @@ -551,15 +551,11 @@ public class MmsConfig { final TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( Context.TELEPHONY_SERVICE); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) { + try { + Method method = telephonyManager.getClass().getMethod("getLine1NumberForSubscriber", int.class); + return (String) method.invoke(telephonyManager, subId); + } catch (Exception e) { return telephonyManager.getLine1Number(); - } else { - try { - Method method = telephonyManager.getClass().getMethod("getLine1NumberForSubscriber", int.class); - return (String) method.invoke(telephonyManager, subId); - } catch (Exception e) { - return telephonyManager.getLine1Number(); - } } } @@ -581,16 +577,12 @@ public class MmsConfig { String nai = ""; - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) { + try { + Method method = telephonyManager.getClass().getMethod("getNai", int.class); + Method getSlotId = SubscriptionManager.class.getMethod("getSlotId", int.class); + nai = (String) method.invoke(telephonyManager, getSlotId.invoke(null, subId)); + } catch (Exception e) { nai = SystemPropertiesProxy.get(context, "persist.radio.cdma.nai"); - } else { - try { - Method method = telephonyManager.getClass().getMethod("getNai", int.class); - Method getSlotId = SubscriptionManager.class.getMethod("getSlotId", int.class); - nai = (String) method.invoke(telephonyManager, getSlotId.invoke(null, subId)); - } catch (Exception e) { - nai = SystemPropertiesProxy.get(context, "persist.radio.cdma.nai"); - } } Timber.v("MmsConfig.getNai: nai=" + nai); diff --git a/android-smsmms/src/main/java/com/android/mms/service_alt/MmsConfigManager.java b/android-smsmms/src/main/java/com/android/mms/service_alt/MmsConfigManager.java index 1f1aca0abae4a44c55ef7152b36f9d97f3fa46e9..a95170df8784cf1cd603a3c21c6a2ddbe1100443 100755 --- a/android-smsmms/src/main/java/com/android/mms/service_alt/MmsConfigManager.java +++ b/android-smsmms/src/main/java/com/android/mms/service_alt/MmsConfigManager.java @@ -73,24 +73,19 @@ public class MmsConfigManager { public void init(final Context context) { mContext = context; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - mSubscriptionManager = SubscriptionManager.from(context); + mSubscriptionManager = SubscriptionManager.from(context); - // TODO: When this object "finishes" we should unregister. - IntentFilter intentFilterLoaded = - new IntentFilter("LOADED"); + // TODO: When this object "finishes" we should unregister. + IntentFilter intentFilterLoaded = new IntentFilter("LOADED"); - try { - context.registerReceiver(mReceiver, intentFilterLoaded); - } catch (Exception e) { + try { + context.registerReceiver(mReceiver, intentFilterLoaded); + } catch (Exception e) { - } - - load(context); - } else { - load(context); } + load(context); + // TODO: When this object "finishes" we should unregister by invoking // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener); // This is not strictly necessary because it will be unregistered if the @@ -151,39 +146,37 @@ public class MmsConfigManager { * */ private void load(Context context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - List subs = mSubscriptionManager.getActiveSubscriptionInfoList(); - if (subs == null || subs.size() < 1) { - Timber.e("MmsConfigManager.load -- empty getActiveSubInfoList"); - return; - } - // Load all the mms_config.xml files in a separate map and then swap with the - // real map at the end so we don't block anyone sync'd on the real map. - final Map newConfigMap = new ArrayMap(); - for (SubscriptionInfo sub : subs) { - Configuration configuration = new Configuration(); - if (sub.getMcc() == 0 && sub.getMnc() == 0) { - Configuration config = mContext.getResources().getConfiguration(); - configuration.mcc = config.mcc; - configuration.mnc = config.mnc; - Timber.i("MmsConfigManager.load -- no mcc/mnc for sub: " + sub + - " using mcc/mnc from main context: " + configuration.mcc + "/" + - configuration.mnc); - } else { - Timber.i("MmsConfigManager.load -- mcc/mnc for sub: " + sub); - - configuration.mcc = sub.getMcc(); - configuration.mnc = sub.getMnc(); - } - Context subContext = context.createConfigurationContext(configuration); - - int subId = sub.getSubscriptionId(); - newConfigMap.put(subId, new MmsConfig(subContext, subId)); - } - synchronized (mSubIdConfigMap) { - mSubIdConfigMap.clear(); - mSubIdConfigMap.putAll(newConfigMap); + List subs = mSubscriptionManager.getActiveSubscriptionInfoList(); + if (subs == null || subs.size() < 1) { + Timber.e("MmsConfigManager.load -- empty getActiveSubInfoList"); + return; + } + // Load all the mms_config.xml files in a separate map and then swap with the + // real map at the end so we don't block anyone sync'd on the real map. + final Map newConfigMap = new ArrayMap(); + for (SubscriptionInfo sub : subs) { + Configuration configuration = new Configuration(); + if (sub.getMcc() == 0 && sub.getMnc() == 0) { + Configuration config = mContext.getResources().getConfiguration(); + configuration.mcc = config.mcc; + configuration.mnc = config.mnc; + Timber.i("MmsConfigManager.load -- no mcc/mnc for sub: " + sub + + " using mcc/mnc from main context: " + configuration.mcc + "/" + + configuration.mnc); + } else { + Timber.i("MmsConfigManager.load -- mcc/mnc for sub: " + sub); + + configuration.mcc = sub.getMcc(); + configuration.mnc = sub.getMnc(); } + Context subContext = context.createConfigurationContext(configuration); + + int subId = sub.getSubscriptionId(); + newConfigMap.put(subId, new MmsConfig(subContext, subId)); + } + synchronized (mSubIdConfigMap) { + mSubIdConfigMap.clear(); + mSubIdConfigMap.putAll(newConfigMap); } } diff --git a/android-smsmms/src/main/java/com/android/mms/service_alt/MmsNetworkManager.java b/android-smsmms/src/main/java/com/android/mms/service_alt/MmsNetworkManager.java index ce3fe460e3b92c948bd9c04ad352da5e0c6b912c..e3092499d5155971522a2683fbf839ea6d3299ca 100755 --- a/android-smsmms/src/main/java/com/android/mms/service_alt/MmsNetworkManager.java +++ b/android-smsmms/src/main/java/com/android/mms/service_alt/MmsNetworkManager.java @@ -87,18 +87,11 @@ public class MmsNetworkManager implements com.squareup.okhttp.internal.Network { mSubId = subId; if (!MmsRequest.useWifi(context)) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - mNetworkRequest = new NetworkRequest.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS) - .setNetworkSpecifier(Integer.toString(mSubId)) - .build(); - } else { - mNetworkRequest = new NetworkRequest.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS) - .build(); - } + mNetworkRequest = new NetworkRequest.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS) + .setNetworkSpecifier(Integer.toString(mSubId)) + .build(); } else { mNetworkRequest = new NetworkRequest.Builder() .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) diff --git a/android-smsmms/src/main/java/com/android/mms/service_alt/MmsRequest.java b/android-smsmms/src/main/java/com/android/mms/service_alt/MmsRequest.java index 7ba80c0728c25934c59eebfc94da1e76bcb79e18..2328d347983cd79b8daf7b29c7177118226c8cbd 100755 --- a/android-smsmms/src/main/java/com/android/mms/service_alt/MmsRequest.java +++ b/android-smsmms/src/main/java/com/android/mms/service_alt/MmsRequest.java @@ -16,32 +16,19 @@ package com.android.mms.service_alt; -import android.app.Activity; -import android.app.PendingIntent; import android.content.Context; -import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; -import android.net.wifi.WifiManager; -import android.os.Build; import android.os.Bundle; -import android.provider.Settings; -import android.service.carrier.CarrierMessagingService; -import android.telephony.SmsManager; -import android.telephony.TelephonyManager; -import com.android.mms.service_alt.exception.ApnException; -import com.android.mms.service_alt.exception.MmsHttpException; + import com.klinker.android.send_message.Utils; -import timber.log.Timber; /** * Base class for MMS requests. This has the common logic of sending/downloading MMS. */ public abstract class MmsRequest { - private static final int RETRY_TIMES = 3; - /** * Interface for certain functionalities from MmsService */ @@ -86,8 +73,6 @@ public abstract class MmsRequest { // MMS config overrides protected Bundle mMmsConfigOverrides; - private boolean mobileDataEnabled; - public MmsRequest(RequestManager requestManager, int subId, String creator, Bundle configOverrides) { mRequestManager = requestManager; @@ -101,192 +86,6 @@ public abstract class MmsRequest { return mSubId; } - private boolean ensureMmsConfigLoaded() { - if (mMmsConfig == null) { - final MmsConfig config; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - // Not yet retrieved from mms config manager. Try getting it. - config = MmsConfigManager.getInstance().getMmsConfigBySubId(mSubId); - } else { - config = MmsConfigManager.getInstance().getMmsConfig(); - } - - if (config != null) { - mMmsConfig = new MmsConfig.Overridden(config, mMmsConfigOverrides); - } - } - return mMmsConfig != null; - } - - private static boolean inAirplaneMode(final Context context) { - return Settings.System.getInt(context.getContentResolver(), - Settings.Global.AIRPLANE_MODE_ON, 0) != 0; - } - - private static boolean isMobileDataEnabled(final Context context, final int subId) { - final TelephonyManager telephonyManager = - (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - return Utils.isDataEnabled(telephonyManager, subId); - } - - private static boolean isDataNetworkAvailable(final Context context, final int subId) { - return !inAirplaneMode(context) && isMobileDataEnabled(context, subId); - } - - /** - * Execute the request - * - * @param context The context - * @param networkManager The network manager to use - */ - public void execute(Context context, MmsNetworkManager networkManager) { - int result = SmsManager.MMS_ERROR_UNSPECIFIED; - int httpStatusCode = 0; - byte[] response = null; - - WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); - boolean isWifiEnabled = wifi.isWifiEnabled(); - - if (!useWifi(context)) { - wifi.setWifiEnabled(false); - } - - mobileDataEnabled = Utils.isMobileDataEnabled(context); - Timber.v("mobile data enabled: " + mobileDataEnabled); - - if (!mobileDataEnabled && !useWifi(context)) { - Timber.v("mobile data not enabled, so forcing it to enable"); - Utils.setMobileDataEnabled(context, true); - } - - if (!ensureMmsConfigLoaded()) { // Check mms config - Timber.e("MmsRequest: mms config is not loaded yet"); - result = SmsManager.MMS_ERROR_CONFIGURATION_ERROR; - } else if (!prepareForHttpRequest()) { // Prepare request, like reading pdu data from user - Timber.e("MmsRequest: failed to prepare for request"); - result = SmsManager.MMS_ERROR_IO_ERROR; - } else if (!isDataNetworkAvailable(context, mSubId)) { - Timber.e("MmsRequest: in airplane mode or mobile data disabled"); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - result = SmsManager.MMS_ERROR_NO_DATA_NETWORK; - } else { - result = 8; - } - } else { // Execute - long retryDelaySecs = 2; - // Try multiple times of MMS HTTP request - for (int i = 0; i < RETRY_TIMES; i++) { - try { - try { - networkManager.acquireNetwork(); - } catch (Exception e) { - Timber.e(e, "error acquiring network"); - } - - final String apnName = networkManager.getApnName(); - try { - ApnSettings apn = null; - try { - apn = ApnSettings.load(context, apnName, mSubId); - } catch (ApnException e) { - // If no APN could be found, fall back to trying without the APN name - if (apnName == null) { - // If the APN name was already null then don't need to retry - throw (e); - } - Timber.i("MmsRequest: No match with APN name:" - + apnName + ", try with no name"); - apn = ApnSettings.load(context, null, mSubId); - } - Timber.i("MmsRequest: using " + apn.toString()); - response = doHttp(context, networkManager, apn); - result = Activity.RESULT_OK; - // Success - break; - } finally { - networkManager.releaseNetwork(); - } - } catch (ApnException e) { - Timber.e(e, "MmsRequest: APN failure"); - result = SmsManager.MMS_ERROR_INVALID_APN; - break; -// } catch (MmsNetworkException e) { -// Timber.e(e, "MmsRequest: MMS network acquiring failure"); -// result = SmsManager.MMS_ERROR_UNABLE_CONNECT_MMS; -// // Retry - } catch (MmsHttpException e) { - Timber.e(e, "MmsRequest: HTTP or network I/O failure"); - result = SmsManager.MMS_ERROR_HTTP_FAILURE; - httpStatusCode = e.getStatusCode(); - // Retry - } catch (Exception e) { - Timber.e(e, "MmsRequest: unexpected failure"); - result = SmsManager.MMS_ERROR_UNSPECIFIED; - break; - } - try { - Thread.sleep(retryDelaySecs * 1000, 0/*nano*/); - } catch (InterruptedException e) { - } - retryDelaySecs <<= 1; - } - } - - if (!mobileDataEnabled) { - Timber.v("setting mobile data back to disabled"); - Utils.setMobileDataEnabled(context, false); - } - - if (!useWifi(context)) { - wifi.setWifiEnabled(isWifiEnabled); - } - - processResult(context, result, response, httpStatusCode); - } - - /** - * Process the result of the completed request, including updating the message status - * in database and sending back the result via pending intents. - * @param context The context - * @param result The result code of execution - * @param response The response body - * @param httpStatusCode The optional http status code in case of http failure - */ - public void processResult(Context context, int result, byte[] response, int httpStatusCode) { - final Uri messageUri = persistIfRequired(context, result, response); - - // Return MMS HTTP request result via PendingIntent - final PendingIntent pendingIntent = getPendingIntent(); - if (pendingIntent != null) { - boolean succeeded = true; - // Extra information to send back with the pending intent - Intent fillIn = new Intent(); - if (response != null) { - succeeded = transferResponse(fillIn, response); - } - if (messageUri != null) { - fillIn.putExtra("uri", messageUri.toString()); - } - if (result == SmsManager.MMS_ERROR_HTTP_FAILURE && httpStatusCode != 0) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - fillIn.putExtra(SmsManager.EXTRA_MMS_HTTP_STATUS, httpStatusCode); - } else { - fillIn.putExtra("android.telephony.extra.MMS_HTTP_STATUS", httpStatusCode); - } - } - try { - if (!succeeded) { - result = SmsManager.MMS_ERROR_IO_ERROR; - } - pendingIntent.send(context, result, fillIn); - } catch (PendingIntent.CanceledException e) { - Timber.e(e, "MmsRequest: sending pending intent canceled"); - } - } - - revokeUriPermission(context); - } - /** * are we set up to use wifi? if so, send mms over it. */ @@ -303,90 +102,4 @@ public abstract class MmsRequest { return false; } - /** - * Returns true if sending / downloading using the carrier app has failed and completes the - * action using platform API's, otherwise false. - */ - protected boolean maybeFallbackToRegularDelivery(int carrierMessagingAppResult) { - if (carrierMessagingAppResult - == CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK - || carrierMessagingAppResult - == CarrierMessagingService.DOWNLOAD_STATUS_RETRY_ON_CARRIER_NETWORK) { - Timber.d("Sending/downloading MMS by IP failed."); - mRequestManager.addSimRequest(MmsRequest.this); - return true; - } else { - return false; - } - } - - /** - * Converts from {@code carrierMessagingAppResult} to a platform result code. - */ - protected static int toSmsManagerResult(int carrierMessagingAppResult) { - switch (carrierMessagingAppResult) { - case CarrierMessagingService.SEND_STATUS_OK: - return Activity.RESULT_OK; - case CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK: - return SmsManager.MMS_ERROR_RETRY; - default: - return SmsManager.MMS_ERROR_UNSPECIFIED; - } - } - - /** - * Making the HTTP request to MMSC - * - * @param context The context - * @param netMgr The current {@link MmsNetworkManager} - * @param apn The APN setting - * @return The HTTP response data - * @throws MmsHttpException If any network error happens - */ - protected abstract byte[] doHttp(Context context, MmsNetworkManager netMgr, ApnSettings apn) - throws MmsHttpException; - - /** - * @return The PendingIntent associate with the MMS sending invocation - */ - protected abstract PendingIntent getPendingIntent(); - - /** - * @return The queue should be used by this request, 0 is sending and 1 is downloading - */ - protected abstract int getQueueType(); - - /** - * Persist message into telephony if required (i.e. when auto-persisting is on or - * the calling app is non-default sms app for sending) - * - * @param context The context - * @param result The result code of execution - * @param response The response body - * @return The persisted URI of the message or null if we don't persist or fail - */ - protected abstract Uri persistIfRequired(Context context, int result, byte[] response); - - /** - * Prepare to make the HTTP request - will download message for sending - * @return true if preparation succeeds (and request can proceed) else false - */ - protected abstract boolean prepareForHttpRequest(); - - /** - * Transfer the received response to the caller - * - * @param fillIn the intent that will be returned to the caller - * @param response the pdu to transfer - * @return true if response transfer succeeds else false - */ - protected abstract boolean transferResponse(Intent fillIn, byte[] response); - - /** - * Revoke the content URI permission granted by the MMS app to the phone package. - * - * @param context The context - */ - protected abstract void revokeUriPermission(Context context); - } diff --git a/android-smsmms/src/main/java/com/android/mms/service_alt/SubscriptionIdChecker.java b/android-smsmms/src/main/java/com/android/mms/service_alt/SubscriptionIdChecker.java index afff0de0babbc632aa6d25fbcdde60bbc457ab6d..611b9509b31df655183eb3a03138a0ca08b135f3 100755 --- a/android-smsmms/src/main/java/com/android/mms/service_alt/SubscriptionIdChecker.java +++ b/android-smsmms/src/main/java/com/android/mms/service_alt/SubscriptionIdChecker.java @@ -16,21 +16,19 @@ class SubscriptionIdChecker { // I met a device which does not have Telephony.Mms.SUBSCRIPTION_ID event if it's API Level is 22. private void check(Context context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - Cursor c = null; - try { - c = SqliteWrapper.query(context, context.getContentResolver(), - Telephony.Mms.CONTENT_URI, - new String[]{Telephony.Mms.SUBSCRIPTION_ID}, null, null, null); - if (c != null) { - mCanUseSubscriptionId = true; - } - } catch (SQLiteException e) { - Timber.e("SubscriptionIdChecker.check() fail"); - } finally { - if (c != null) { - c.close(); - } + Cursor c = null; + try { + c = SqliteWrapper.query(context, context.getContentResolver(), + Telephony.Mms.CONTENT_URI, + new String[]{Telephony.Mms.SUBSCRIPTION_ID}, null, null, null); + if (c != null) { + mCanUseSubscriptionId = true; + } + } catch (SQLiteException e) { + Timber.e("SubscriptionIdChecker.check() fail"); + } finally { + if (c != null) { + c.close(); } } } diff --git a/android-smsmms/src/main/java/com/android/mms/transaction/DownloadManager.java b/android-smsmms/src/main/java/com/android/mms/transaction/DownloadManager.java index 698817ca6d3364cfbd1325e688492837f123639c..a8f6de5ffd797b251d48fd7d991d7c172ff0cb8f 100755 --- a/android-smsmms/src/main/java/com/android/mms/transaction/DownloadManager.java +++ b/android-smsmms/src/main/java/com/android/mms/transaction/DownloadManager.java @@ -73,7 +73,7 @@ public class DownloadManager { download.putExtra(MmsReceivedReceiver.EXTRA_TRIGGER_PUSH, byPush); download.putExtra(MmsReceivedReceiver.EXTRA_URI, uri); final PendingIntent pendingIntent = PendingIntent.getBroadcast( - context, 0, download, PendingIntent.FLAG_CANCEL_CURRENT); + context, 0, download, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); final SmsManager smsManager = SmsManagerFactory.INSTANCE.createSmsManager(subscriptionId); Bundle configOverrides = new Bundle(); diff --git a/android-smsmms/src/main/java/com/android/mms/transaction/RetrieveTransaction.java b/android-smsmms/src/main/java/com/android/mms/transaction/RetrieveTransaction.java index 4de1c9b8a83177c8bbdf9881be1a675fe31afaf0..238d5ef879e0a9f7afba21fd111c18fba8b7795c 100755 --- a/android-smsmms/src/main/java/com/android/mms/transaction/RetrieveTransaction.java +++ b/android-smsmms/src/main/java/com/android/mms/transaction/RetrieveTransaction.java @@ -124,11 +124,6 @@ public class RetrieveTransaction extends Transaction implements Runnable { } public void run() { -// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { -// DownloadRequest request = new DownloadRequest(mContentLocation, mUri, null, null, null); -// MmsNetworkManager manager = new MmsNetworkManager(mContext); -// request.execute(mContext, manager); -// } else { try { // Change the downloading state of the M-Notification.ind. DownloadManager.init(mContext.getApplicationContext()); diff --git a/android-smsmms/src/main/java/com/android/mms/transaction/RetryScheduler.java b/android-smsmms/src/main/java/com/android/mms/transaction/RetryScheduler.java index 455581810a80308a96fe164a5670448692d53dfb..414f14e7eb56c02e4ac4a03a6ef171854c84b7a7 100755 --- a/android-smsmms/src/main/java/com/android/mms/transaction/RetryScheduler.java +++ b/android-smsmms/src/main/java/com/android/mms/transaction/RetryScheduler.java @@ -309,7 +309,7 @@ public class RetryScheduler implements Observer { Intent service = new Intent(TransactionService.ACTION_ONALARM, null, context, TransactionService.class); PendingIntent operation = PendingIntent.getService( - context, 0, service, PendingIntent.FLAG_ONE_SHOT); + context, 0, service, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE); AlarmManager am = (AlarmManager) context.getSystemService( Context.ALARM_SERVICE); am.set(AlarmManager.RTC, retryAt, operation); diff --git a/android-smsmms/src/main/java/com/android/mms/transaction/TransactionService.java b/android-smsmms/src/main/java/com/android/mms/transaction/TransactionService.java index 78146c9ea2553143a7fb7a83dc0f91483871f43a..299740a3e91b9decd232698a0a5b063332d1f1d7 100755 --- a/android-smsmms/src/main/java/com/android/mms/transaction/TransactionService.java +++ b/android-smsmms/src/main/java/com/android/mms/transaction/TransactionService.java @@ -197,33 +197,6 @@ public class TransactionService extends Service implements Observer { @Override public int onStartCommand(final Intent intent, int flags, int startId) { if (intent != null) { -// if (intent.getBooleanExtra(TransactionBundle.LOLLIPOP_RECEIVING, false)) { -// lollipopReceiving = true; -// new Thread(new Runnable() { -// @Override -// public void run() { -// Timber.v("starting receiving with new lollipop method"); -// try { Thread.sleep(60000); } catch (Exception e) { } -// Timber.v("done sleeping, lets try and grab the message"); -// Uri contentUri = Uri.parse(intent.getStringExtra(TransactionBundle.URI)); -// String downloadLocation = null; -// Cursor locationQuery = getContentResolver().query(contentUri, new String[]{Telephony.Mms.CONTENT_LOCATION, Telephony.Mms._ID}, null, null, "date desc"); -// -// if (locationQuery != null && locationQuery.moveToFirst()) { -// Timber.v("grabbing content location url"); -// downloadLocation = locationQuery.getString(locationQuery.getColumnIndex(Telephony.Mms.CONTENT_LOCATION)); -// } -// -// Timber.v("creating request with url: " + downloadLocation); -// DownloadRequest request = new DownloadRequest(downloadLocation, contentUri, null, null, null); -// MmsNetworkManager manager = new MmsNetworkManager(TransactionService.this); -// request.execute(TransactionService.this, manager); -// stopSelf(); -// } -// }).start(); -// return START_NOT_STICKY; -// } - if (mServiceHandler == null) { initServiceHandler(); } @@ -539,11 +512,6 @@ public class TransactionService extends Service implements Observer { // cancel timer for renewal of lease mServiceHandler.removeMessages(EVENT_CONTINUE_MMS_CONNECTIVITY); - if (mConnMgr != null && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - mConnMgr.stopUsingNetworkFeature( - ConnectivityManager.TYPE_MOBILE, - "enableMMS"); - } } finally { releaseWakeLock(); } diff --git a/android-smsmms/src/main/java/com/android/mms/transaction/TransactionSettings.java b/android-smsmms/src/main/java/com/android/mms/transaction/TransactionSettings.java index 242fb417d8db54fd9965fccc3311e25ee8e595cc..9490215cceb479d74d1517928a494c95d6f35118 100755 --- a/android-smsmms/src/main/java/com/android/mms/transaction/TransactionSettings.java +++ b/android-smsmms/src/main/java/com/android/mms/transaction/TransactionSettings.java @@ -35,17 +35,6 @@ public class TransactionSettings { private String mProxyAddress; private int mProxyPort = -1; - private static final String[] APN_PROJECTION = { - Telephony.Carriers.TYPE, // 0 - Telephony.Carriers.MMSC, // 1 - Telephony.Carriers.MMSPROXY, // 2 - Telephony.Carriers.MMSPORT // 3 - }; - private static final int COLUMN_TYPE = 0; - private static final int COLUMN_MMSC = 1; - private static final int COLUMN_MMSPROXY = 2; - private static final int COLUMN_MMSPORT = 3; - /** * Constructor that uses the default settings of the MMS Client. * @@ -53,29 +42,6 @@ public class TransactionSettings { */ public TransactionSettings(Context context, String apnName) { Timber.v("TransactionSettings: apnName: " + apnName); -// String selection = "current" + " IS NOT NULL"; -// String[] selectionArgs = null; -// if (!TextUtils.isEmpty(apnName)) { -// selection += " AND " + "apn" + "=?"; -// selectionArgs = new String[]{ apnName.trim() }; -// } -// -// Cursor cursor; -// -// try { -// cursor = SqliteWrapper.query(context, context.getContentResolver(), -// Telephony.Carriers.CONTENT_URI, -// APN_PROJECTION, selection, selectionArgs, null); -// -// Timber.v("TransactionSettings looking for apn: " + selection + " returned: " + -// (cursor == null ? "null cursor" : (cursor.getCount() + " hits"))); -// } catch (SecurityException e) { -// Timber.e(e, "exception thrown"); -// cursor = null; -// } -// -// if (cursor == null) { -// Timber.e("Apn is not found in Database!"); if (Transaction.Companion.getSettings() == null) { Transaction.Companion.setSettings(Utils.getDefaultSendSettings(context)); } @@ -109,46 +75,6 @@ public class TransactionSettings { Timber.e(e, "could not get proxy: " + Transaction.Companion.getSettings().getPort()); } } -// } - -// boolean sawValidApn = false; -// try { -// while (cursor.moveToNext() && TextUtils.isEmpty(mServiceCenter)) { -// // Read values from APN settings -// if (isValidApnType(cursor.getString(COLUMN_TYPE), "mms")) { -// sawValidApn = true; -// -// String mmsc = cursor.getString(COLUMN_MMSC); -// if (mmsc == null) { -// continue; -// } -// -// mServiceCenter = NetworkUtils.trimV4AddrZeros(mmsc.trim()); -// mProxyAddress = NetworkUtils.trimV4AddrZeros( -// cursor.getString(COLUMN_MMSPROXY)); -// if (isProxySet()) { -// String portString = cursor.getString(COLUMN_MMSPORT); -// try { -// mProxyPort = Integer.parseInt(portString); -// } catch (NumberFormatException e) { -// if (TextUtils.isEmpty(portString)) { -// Timber.w("mms port not set!"); -// } else { -// Timber.e(e, "Bad port number format: " + portString); -// } -// } -// } -// } -// } -// } finally { -// cursor.close(); -// } -// -// Timber.v("APN setting: MMSC: " + mServiceCenter + " looked for: " + selection); -// -// if (sawValidApn && TextUtils.isEmpty(mServiceCenter)) { -// Timber.e("Invalid APN setting: MMSC is empty"); -// } } /** @@ -186,17 +112,4 @@ public class TransactionSettings { return (mProxyAddress != null) && (mProxyAddress.trim().length() != 0); } - static private boolean isValidApnType(String types, String requestType) { - // If APN type is unspecified, assume APN_TYPE_ALL. - if (TextUtils.isEmpty(types)) { - return true; - } - - for (String t : types.split(",")) { - if (t.equals(requestType) || t.equals("*")) { - return true; - } - } - return false; - } } diff --git a/android-smsmms/src/main/java/com/google/android/mms/pdu_alt/PduPersister.java b/android-smsmms/src/main/java/com/google/android/mms/pdu_alt/PduPersister.java index 07bcb551f0f1cf454de17326bd81215c5a79e52a..10ea303ebf89e46ed8663559817f4b5bf261290b 100755 --- a/android-smsmms/src/main/java/com/google/android/mms/pdu_alt/PduPersister.java +++ b/android-smsmms/src/main/java/com/google/android/mms/pdu_alt/PduPersister.java @@ -1604,8 +1604,6 @@ public class PduPersister { * Check if read permissions for SMS have been granted */ private boolean checkReadSmsPermissions() { - return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || - mContext.checkSelfPermission(Manifest.permission.READ_SMS) == - PackageManager.PERMISSION_GRANTED; + return mContext.checkSelfPermission(Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED; } } diff --git a/android-smsmms/src/main/java/com/klinker/android/send_message/SmsManagerFactory.kt b/android-smsmms/src/main/java/com/klinker/android/send_message/SmsManagerFactory.kt index 10d078e43c9eea2da47e7a1695ca7db76287bf94..2f239384294a9516e0e25747cc5322e6ff670caa 100755 --- a/android-smsmms/src/main/java/com/klinker/android/send_message/SmsManagerFactory.kt +++ b/android-smsmms/src/main/java/com/klinker/android/send_message/SmsManagerFactory.kt @@ -1,6 +1,5 @@ package com.klinker.android.send_message -import android.os.Build import android.telephony.SmsManager object SmsManagerFactory { @@ -8,7 +7,7 @@ object SmsManagerFactory { fun createSmsManager(subscriptionId: Int): SmsManager { var manager: SmsManager? = null - if (subscriptionId != -1 && Build.VERSION.SDK_INT >= 22) { + if (subscriptionId != -1) { try { manager = SmsManager.getSmsManagerForSubscriptionId(subscriptionId) } catch (e: Exception) { diff --git a/android-smsmms/src/main/java/com/klinker/android/send_message/Transaction.kt b/android-smsmms/src/main/java/com/klinker/android/send_message/Transaction.kt index 35912778fce454c089b98c3fdda7f6fbc3f38dcc..259d9c1f90f6b8d4295875a2027c97531a46f75c 100755 --- a/android-smsmms/src/main/java/com/klinker/android/send_message/Transaction.kt +++ b/android-smsmms/src/main/java/com/klinker/android/send_message/Transaction.kt @@ -101,7 +101,7 @@ class Transaction @JvmOverloads constructor(private val context: Context, settin sentIntent.putExtra(EXTRA_CONTENT_URI, messageUri.toString()) sentIntent.putExtra(EXTRA_FILE_PATH, sendFile.path) - val sentPI = PendingIntent.getBroadcast(context, 0, sentIntent, PendingIntent.FLAG_CANCEL_CURRENT) + val sentPI = PendingIntent.getBroadcast(context, 0, sentIntent, PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE) val updatedIntent = Intent(MMS_UPDATED).putExtra("uri", messageUri.toString()) BroadcastUtils.addClassName(context, updatedIntent, MMS_UPDATED) diff --git a/android-smsmms/src/main/java/com/klinker/android/send_message/Utils.java b/android-smsmms/src/main/java/com/klinker/android/send_message/Utils.java index 2fc446932950f2f15d4a3412e346373df2461d49..5851cd8f8f0856dbebcc3d20dcb0e3318d772d25 100755 --- a/android-smsmms/src/main/java/com/klinker/android/send_message/Utils.java +++ b/android-smsmms/src/main/java/com/klinker/android/send_message/Utils.java @@ -59,14 +59,9 @@ public class Utils { } public static T ensureRouteToMmsNetwork(Context context, String url, String proxy, Task task) throws IOException { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - return ensureRouteToMmsNetworkMarshmallow(context, task); - } else { - return ensureRouteToMmsNetworkLollipop(context, task); - } + return ensureRouteToMmsNetworkMarshmallow(context, task); } - @TargetApi(Build.VERSION_CODES.M) private static T ensureRouteToMmsNetworkMarshmallow(Context context, Task task) throws IOException { final MmsNetworkManager networkManager = new MmsNetworkManager(context.getApplicationContext(), Utils.getDefaultSubscriptionId()); final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); @@ -85,24 +80,6 @@ public class Utils { } } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - private static T ensureRouteToMmsNetworkLollipop(Context context, Task task) throws IOException { - final MmsNetworkManager networkManager = new MmsNetworkManager(context.getApplicationContext(), Utils.getDefaultSubscriptionId()); - Network network = null; - try { - network = networkManager.acquireNetwork(); - ConnectivityManager.setProcessDefaultNetwork(network); - return task.run(); - } catch (MmsNetworkException e) { - throw new IOException(e); - } finally { - if (network != null) { - ConnectivityManager.setProcessDefaultNetwork(null); - } - networkManager.releaseNetwork(); - } - } - /** * Ensures that the host MMSC is reachable * @@ -296,18 +273,6 @@ public class Utils { //throw new IllegalArgumentException("Unable to find or allocate a thread ID."); } - public static boolean doesThreadIdExist(Context context, long threadId) { - Uri uri = Uri.parse("content://mms-sms/conversations/" + threadId + "/"); - - Cursor cursor = context.getContentResolver().query(uri, new String[] {"_id"}, null, null, null); - if (cursor != null && cursor.moveToFirst()) { - cursor.close(); - return true; - } else { - return false; - } - } - private static boolean isEmailAddress(String address) { if (TextUtils.isEmpty(address)) { return false; @@ -381,10 +346,6 @@ public class Utils { } public static int getDefaultSubscriptionId() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { - return SmsManager.getDefaultSmsSubscriptionId(); - } else { - return DEFAULT_SUBSCRIPTION_ID; - } + return SmsManager.getDefaultSmsSubscriptionId(); } } diff --git a/build.gradle b/build.gradle index c0736ee3c315b5623aaa73db3b7ca1f5f80f412f..c04f17cdc57bb19e5ddb799396cb37e642e2af10 100644 --- a/build.gradle +++ b/build.gradle @@ -1,15 +1,16 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.androidx_appcompat_version = '1.1.0' + ext.androidx_appcompat_version = '1.3.1' ext.androidx_constraintlayout_version = '1.1.3' ext.androidx_core_version = '1.1.0' + ext.androidx_documentfile_version = '1.0.1' ext.androidx_emoji_version = '1.0.0' ext.androidx_exifinterface_version = '1.0.0' ext.androidx_testrunner_version = '1.1.0-alpha3' ext.androidx_viewpager_version = '1.0.0-beta05' ext.autodispose_version = '1.3.0' - ext.billing_version = '3.0.2' + ext.billing_version = '5.1.0' ext.conductor_version = '2.1.5' ext.coroutines_version = '1.4.3' ext.dagger_version = "2.16" @@ -17,13 +18,13 @@ buildscript { ext.exoplayer_version = "2.8.1" ext.glide_version = "4.8.0" ext.junit_version = '4.12' - ext.kotlin_version = '1.3.60' + ext.kotlin_version = '1.7.20' ext.lifecycle_version = '2.1.0' ext.material_version = '1.0.0' ext.mockito_version = '2.18.3' ext.moshi_version = '1.8.0' - ext.okhttp3_version = '4.1.0' - ext.realm_version = '5.8.0' + ext.okhttp3_version = '4.10.0' + ext.realm_version = '10.13.0' ext.realm_adapters_version = '3.1.0' ext.rxandroid_version = '2.0.1' ext.rxdogtag_version = '0.2.0' @@ -40,9 +41,9 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.5.4' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1' - classpath 'com.google.gms:google-services:4.2.0' + classpath 'com.android.tools.build:gradle:7.3.1' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.2' + classpath 'com.google.gms:google-services:4.3.14' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "io.realm:realm-gradle-plugin:$realm_version" } diff --git a/common/build.gradle b/common/build.gradle index a893d1c184c792d8de3febcf74f8423af7634ccb..21a56b45bc6700a945958b5861efb1a9ed407984 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -20,14 +20,15 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' android { - compileSdkVersion 29 + compileSdkVersion 33 defaultConfig { - minSdkVersion 21 - targetSdkVersion 29 + minSdkVersion 23 + targetSdkVersion 33 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + namespace 'com.moez.QKSMS.common' } dependencies { diff --git a/common/src/main/AndroidManifest.xml b/common/src/main/AndroidManifest.xml index 969a751c5cf2b22cbe2ce7119ded8abfa6278a88..21edd1fd3fb231816cc9f4a8c0583ce2367d42e5 100644 --- a/common/src/main/AndroidManifest.xml +++ b/common/src/main/AndroidManifest.xml @@ -16,4 +16,4 @@ ~ You should have received a copy of the GNU General Public License ~ along with QKSMS. If not, see . --> - + diff --git a/common/src/main/java/com/moez/QKSMS/compat/TelephonyCompat.kt b/common/src/main/java/com/moez/QKSMS/compat/TelephonyCompat.kt index c8fa84bdbf6283291f7879d759674ecf989a49c4..9f88e83a1108f8072a7b3db20e74ec29cf28b04b 100644 --- a/common/src/main/java/com/moez/QKSMS/compat/TelephonyCompat.kt +++ b/common/src/main/java/com/moez/QKSMS/compat/TelephonyCompat.kt @@ -42,28 +42,7 @@ object TelephonyCompat { } fun getOrCreateThreadId(context: Context, recipients: Collection): Long { - return if (Build.VERSION.SDK_INT >= 23) { - Telephony.Threads.getOrCreateThreadId(context, recipients.toSet()) - } else { - val uriBuilder = THREAD_ID_CONTENT_URI.buildUpon() - - recipients - .map { recipient -> if (isEmailAddress(recipient)) extractAddrSpec(recipient) else recipient } - .forEach { recipient -> uriBuilder.appendQueryParameter("recipient", recipient) } - - val uri = uriBuilder.build() - - SqliteWrapper.query(context, context.contentResolver, uri, ID_PROJECTION, null, null, null)?.use { cursor -> - if (cursor.moveToFirst()) { - return cursor.getLong(0) - } else { - Timber.e("getOrCreateThreadId returned no rows!") - } - } - - Timber.e("getOrCreateThreadId failed with " + recipients.size + " recipients") - throw IllegalArgumentException("Unable to find or allocate a thread ID.") - } + return Telephony.Threads.getOrCreateThreadId(context, recipients.toSet()) } fun extractAddrSpec(address: String): String { diff --git a/data/build.gradle b/data/build.gradle index d61add8e7f79af4999247154ddb52b1188d5b958..73170a26ee7825825d9fca9e7ac497026463c6dd 100644 --- a/data/build.gradle +++ b/data/build.gradle @@ -21,7 +21,7 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' android { - compileSdkVersion 29 + compileSdkVersion 33 publishNonDefault true flavorDimensions "analytics" @@ -31,8 +31,8 @@ android { } defaultConfig { - minSdkVersion 21 - targetSdkVersion 29 + minSdkVersion 23 + targetSdkVersion 33 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField "String", "AMPLITUDE_API_KEY", "\"${System.getenv("AMPLITUDE_API_KEY")}\"" @@ -42,6 +42,7 @@ android { withAnalytics { dimension "analytics" } noAnalytics { dimension "analytics" } } + namespace 'com.moez.QKSMS.data' } dependencies { @@ -50,6 +51,7 @@ dependencies { implementation "androidx.appcompat:appcompat:$androidx_appcompat_version" implementation "androidx.core:core-ktx:$androidx_core_version" implementation "androidx.exifinterface:exifinterface:$androidx_exifinterface_version" + implementation "androidx.documentfile:documentfile:$androidx_documentfile_version" // glide implementation "com.github.bumptech.glide:glide:$glide_version" diff --git a/data/src/main/AndroidManifest.xml b/data/src/main/AndroidManifest.xml index 3c6184a70ef843a8c0e18a271ff8f2f19453d4ba..21edd1fd3fb231816cc9f4a8c0583ce2367d42e5 100644 --- a/data/src/main/AndroidManifest.xml +++ b/data/src/main/AndroidManifest.xml @@ -16,4 +16,4 @@ ~ You should have received a copy of the GNU General Public License ~ along with QKSMS. If not, see . --> - + diff --git a/data/src/main/assets/changelog.json b/data/src/main/assets/changelog.json index c4d2e917edc9b15b71d455244cc41e2846ea8ae5..8485028b1c2f3ed7c2797afe5af1a27210bc7acb 100644 --- a/data/src/main/assets/changelog.json +++ b/data/src/main/assets/changelog.json @@ -1,4 +1,26 @@ [ + { + "versionCode": "2220", + "versionName": "3.10.1", + "fixed": [ + "Crash when launching the app" + ] + }, + { + "versionCode": "2219", + "versionName": "3.10.0", + "added": [ + "Support for Call Blocker (blocking manager)" + ], + "improved": [ + "Support for Scoped Storage" + ], + "fixed": [ + "Incorrect handling of shared text that contains a comma", + "Crash in billing flow", + "Crash when viewing VCard attachment with no name" + ] + }, { "versionCode": "2218", "versionName": "3.9.4", diff --git a/data/src/main/java/com/moez/QKSMS/compat/SubscriptionInfoCompat.kt b/data/src/main/java/com/moez/QKSMS/compat/SubscriptionInfoCompat.kt index f6674e4c6380a3ed74017feca3c6f189634248d0..c18561b98587fe774e659b1f8c5987436f093bc0 100644 --- a/data/src/main/java/com/moez/QKSMS/compat/SubscriptionInfoCompat.kt +++ b/data/src/main/java/com/moez/QKSMS/compat/SubscriptionInfoCompat.kt @@ -22,7 +22,6 @@ import android.annotation.TargetApi import android.os.Build import android.telephony.SubscriptionInfo -@TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1) data class SubscriptionInfoCompat(private val subscriptionInfo: SubscriptionInfo) { val subscriptionId get() = subscriptionInfo.subscriptionId diff --git a/data/src/main/java/com/moez/QKSMS/compat/SubscriptionManagerCompat.kt b/data/src/main/java/com/moez/QKSMS/compat/SubscriptionManagerCompat.kt index fb6174ff4222146907cb6a3595ca5204c8f4fa77..4a2e4a2b3d22e56175b8fa5ae73c9f14a9849e61 100644 --- a/data/src/main/java/com/moez/QKSMS/compat/SubscriptionManagerCompat.kt +++ b/data/src/main/java/com/moez/QKSMS/compat/SubscriptionManagerCompat.kt @@ -31,36 +31,29 @@ class SubscriptionManagerCompat @Inject constructor(context: Context, private va val activeSubscriptionInfoList: List get() { - return if (Build.VERSION.SDK_INT >= 22) { - subscriptionManager?.activeSubscriptionInfoList?.map { SubscriptionInfoCompat(it) } ?: listOf() - } else listOf() + return subscriptionManager?.activeSubscriptionInfoList?.map { SubscriptionInfoCompat(it) } ?: listOf() } init { - subscriptionManager = if (Build.VERSION.SDK_INT >= 22) SubscriptionManager.from(context) else null + subscriptionManager = SubscriptionManager.from(context) } fun addOnSubscriptionsChangedListener(listener: OnSubscriptionsChangedListener) { - if (Build.VERSION.SDK_INT >= 22) { - subscriptionManager?.addOnSubscriptionsChangedListener(listener.listener) - } + subscriptionManager?.addOnSubscriptionsChangedListener(listener.listener) } fun removeOnSubscriptionsChangedListener(listener: OnSubscriptionsChangedListener) { - if (Build.VERSION.SDK_INT >= 22) { - subscriptionManager?.removeOnSubscriptionsChangedListener(listener.listener) - } + subscriptionManager?.removeOnSubscriptionsChangedListener(listener.listener) } abstract class OnSubscriptionsChangedListener { - val listener: SubscriptionManager.OnSubscriptionsChangedListener? = if (Build.VERSION.SDK_INT >= 22) { + val listener: SubscriptionManager.OnSubscriptionsChangedListener? = object : SubscriptionManager.OnSubscriptionsChangedListener() { override fun onSubscriptionsChanged() { this@OnSubscriptionsChangedListener.onSubscriptionsChanged() } } - } else null abstract fun onSubscriptionsChanged() diff --git a/data/src/main/java/com/moez/QKSMS/manager/AlarmManagerImpl.kt b/data/src/main/java/com/moez/QKSMS/manager/AlarmManagerImpl.kt index 526d5d0acbaa12889215d773c2f8aed6b4c23161..1d928042141c2a80e3985dbf3983ffade01e7f51 100644 --- a/data/src/main/java/com/moez/QKSMS/manager/AlarmManagerImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/manager/AlarmManagerImpl.kt @@ -29,16 +29,12 @@ class AlarmManagerImpl @Inject constructor(private val context: Context) : Alarm override fun getScheduledMessageIntent(id: Long): PendingIntent { val intent = Intent(context, SendScheduledMessageReceiver::class.java).putExtra("id", id) - return PendingIntent.getBroadcast(context, id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT) + return PendingIntent.getBroadcast(context, id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) } override fun setAlarm(date: Long, intent: PendingIntent) { val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as android.app.AlarmManager - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - alarmManager.setExactAndAllowWhileIdle(android.app.AlarmManager.RTC_WAKEUP, date, intent) - } else { - alarmManager.setExact(android.app.AlarmManager.RTC_WAKEUP, date, intent) - } + alarmManager.setExactAndAllowWhileIdle(android.app.AlarmManager.RTC_WAKEUP, date, intent) } } \ No newline at end of file diff --git a/data/src/main/java/com/moez/QKSMS/manager/PermissionManagerImpl.kt b/data/src/main/java/com/moez/QKSMS/manager/PermissionManagerImpl.kt index 93620b69d2ce42978a4947e8308f4e7b7e896220..93c3b1e1076299210cf75cbe81e6e03ef845a753 100644 --- a/data/src/main/java/com/moez/QKSMS/manager/PermissionManagerImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/manager/PermissionManagerImpl.kt @@ -19,6 +19,8 @@ package com.moez.QKSMS.manager import android.Manifest +import android.app.AlarmManager +import android.app.NotificationManager import android.app.role.RoleManager import android.content.Context import android.content.pm.PackageManager @@ -29,6 +31,8 @@ import javax.inject.Inject class PermissionManagerImpl @Inject constructor(private val context: Context) : PermissionManager { + private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + override fun isDefaultSms(): Boolean { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { context.getSystemService(RoleManager::class.java)?.isRoleHeld(RoleManager.ROLE_SMS) == true @@ -49,6 +53,13 @@ class PermissionManagerImpl @Inject constructor(private val context: Context) : return hasPermission(Manifest.permission.READ_CONTACTS) } + override fun hasNotifications(): Boolean { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) { + return true + } + return notificationManager.areNotificationsEnabled() + } + override fun hasPhone(): Boolean { return hasPermission(Manifest.permission.READ_PHONE_STATE) } @@ -61,6 +72,15 @@ class PermissionManagerImpl @Inject constructor(private val context: Context) : return hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) } + override fun hasExactAlarms(): Boolean { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { + return true + } + + val alarmManager = context.getSystemService(AlarmManager::class.java) + return alarmManager.canScheduleExactAlarms() + } + private fun hasPermission(permission: String): Boolean { return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED } diff --git a/data/src/main/java/com/moez/QKSMS/receiver/DeleteMessagesReceiver.kt b/data/src/main/java/com/moez/QKSMS/receiver/DeleteMessagesReceiver.kt index 7d5e1525240837075d70f8d71685d06c760790af..60fab4f23bffb8cdaf0057949584a485c187b13b 100644 --- a/data/src/main/java/com/moez/QKSMS/receiver/DeleteMessagesReceiver.kt +++ b/data/src/main/java/com/moez/QKSMS/receiver/DeleteMessagesReceiver.kt @@ -34,7 +34,7 @@ class DeleteMessagesReceiver : BroadcastReceiver() { val pendingResult = goAsync() val threadId = intent.getLongExtra("threadId", 0) - val messageIds = intent.getLongArrayExtra("messageIds") + val messageIds = intent.getLongArrayExtra("messageIds") ?: longArrayOf() deleteMessages.execute(DeleteMessages.Params(messageIds.toList(), threadId)) { pendingResult.finish() } } diff --git a/data/src/main/java/com/moez/QKSMS/repository/BackupRepositoryImpl.kt b/data/src/main/java/com/moez/QKSMS/repository/BackupRepositoryImpl.kt index efa51ad6586daf5f238f330df0cbf904cebbd9e5..0a80c7208183765a547fcd39746fadb6694e8abf 100644 --- a/data/src/main/java/com/moez/QKSMS/repository/BackupRepositoryImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/repository/BackupRepositoryImpl.kt @@ -18,27 +18,27 @@ */ package com.moez.QKSMS.repository +import android.annotation.SuppressLint import android.content.Context +import android.content.Intent +import android.net.Uri import android.os.Environment import android.provider.Telephony import androidx.core.content.contentValuesOf -import com.moez.QKSMS.util.FileUtils +import androidx.core.net.toUri +import androidx.documentfile.provider.DocumentFile +import com.moez.QKSMS.common.util.extensions.now import com.moez.QKSMS.model.BackupFile import com.moez.QKSMS.model.Message import com.moez.QKSMS.util.Preferences -import com.moez.QKSMS.util.QkFileObserver -import com.moez.QKSMS.util.tryOrNull import com.squareup.moshi.Moshi import io.reactivex.Observable -import io.reactivex.schedulers.Schedulers import io.reactivex.subjects.BehaviorSubject import io.reactivex.subjects.Subject import io.realm.Realm import okio.buffer import okio.source import timber.log.Timber -import java.io.File -import java.io.FileOutputStream import java.text.SimpleDateFormat import java.util.* import javax.inject.Inject @@ -53,11 +53,6 @@ class BackupRepositoryImpl @Inject constructor( private val syncRepo: SyncRepository ) : BackupRepository { - companion object { - private val OLD_BACKUP_DIRECTORY = Environment.getExternalStorageDirectory().toString() + "/QKSMS/Backups" - private val BACKUP_DIRECTORY = Environment.getExternalStorageDirectory().toString() + "/Message/Backups" - } - data class Backup( val messageCount: Int = 0, val messages: List = listOf() @@ -93,11 +88,35 @@ class BackupRepositoryImpl @Inject constructor( @Volatile private var stopFlag: Boolean = false + override fun getDefaultBackupPath(): String { + return "${Environment.getExternalStorageDirectory()}/Message/Backups" + } + + override fun getBackupDocumentTree(): DocumentFile? { + return prefs.backupDirectory.get() + .takeIf { uri -> uri != Uri.EMPTY } + ?.let { uri -> DocumentFile.fromTreeUri(context, uri) } + ?.takeIf { dir -> dir.exists() && dir.canRead() && dir.canWrite() } + } + + override fun getBackupPathUriForPicker(): Uri { + return prefs.backupDirectory.get().takeIf { uri -> uri != Uri.EMPTY } + ?: getDefaultBackupPath().toUri() + } + + override fun persistBackupDirectory(directory: Uri) { + context.contentResolver.takePersistableUriPermission(directory, + Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION) + prefs.backupDirectory.set(directory) + + Timber.v("Updated backup directory: $directory") + } + override fun performBackup() { // If a backup or restore is already running, don't do anything if (isBackupOrRestoreRunning()) return - var messageCount = 0 + var messageCount: Int // Map all the messages into our object we'll use for the Json mapping val backupMessages = Realm.getDefaultInstance().use { realm -> @@ -121,13 +140,15 @@ class BackupRepositoryImpl @Inject constructor( val json = adapter.toJson(Backup(messageCount, backupMessages)).toByteArray() try { - // Create the directory and file - val dir = File(BACKUP_DIRECTORY).apply { mkdirs() } - val timestamp = SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(System.currentTimeMillis()) - val file = File(dir, "backup-$timestamp.json") - - // Write the log to the file - FileOutputStream(file, true).use { fileOutputStream -> fileOutputStream.write(json) } + val timestamp = SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(now()) + val inputStream = getBackupDocumentTree() + ?.createFile("application/json", "backup-$timestamp.json") + ?.let { file -> context.contentResolver.openOutputStream(file.uri) } + ?: throw Exception("Failed to open output stream") + + inputStream.use { stream -> + stream.write(json) + } } catch (e: Exception) { Timber.w(e) } @@ -153,40 +174,34 @@ class BackupRepositoryImpl @Inject constructor( override fun getBackupProgress(): Observable = backupProgress - override fun getBackups(): Observable> { - FileUtils.moveDir(File(OLD_BACKUP_DIRECTORY), File(BACKUP_DIRECTORY)) - - return QkFileObserver(BACKUP_DIRECTORY).observable - .map { File(BACKUP_DIRECTORY).listFiles() ?: arrayOf() } - .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.computation()) - .map { files -> - files.mapNotNull { file -> - val adapter = moshi.adapter(BackupMetadata::class.java) - val backup = tryOrNull(false) { - file.source().buffer().use(adapter::fromJson) - } ?: return@mapNotNull null - - val path = file.path - val date = file.lastModified() - val messages = backup.messageCount - val size = file.length() - BackupFile(path, date, messages, size) - } - } - .map { files -> files.sortedByDescending { file -> file.date } } + @SuppressLint("Recycle") // InputStream is closed by Okio BufferedSource + override fun parseBackup(uri: Uri): BackupFile { + val adapter = moshi.adapter(BackupMetadata::class.java) + + val file = DocumentFile.fromSingleUri(context, uri) + ?: throw IllegalArgumentException("Couldn't open backup file") + + val metadata = context.contentResolver.openInputStream(file.uri) + ?.source() + ?.buffer() + ?.use(adapter::fromJson) + ?: throw IllegalArgumentException("Couldn't parse backup file") + + return BackupFile(file.lastModified(), metadata.messageCount) } - override fun performRestore(filePath: String) { + override fun performRestore(uri: Uri) { // If a backupFile or restore is already running, don't do anything if (isBackupOrRestoreRunning()) return restoreProgress.onNext(BackupRepository.Progress.Parsing()) - val file = File(filePath) - val backup = file.source().buffer().use { source -> - moshi.adapter(Backup::class.java).fromJson(source) - } + val adapter = moshi.adapter(Backup::class.java) + val backup = DocumentFile.fromSingleUri(context, uri) + ?.let { file -> context.contentResolver.openInputStream(file.uri) } + ?.source() + ?.buffer() + ?.use(adapter::fromJson) val messageCount = backup?.messages?.size ?: 0 var errorCount = 0 @@ -240,12 +255,12 @@ class BackupRepositoryImpl @Inject constructor( Timer().schedule(1000) { restoreProgress.onNext(BackupRepository.Progress.Idle()) } } + override fun getRestoreProgress(): Observable = restoreProgress + override fun stopRestore() { stopFlag = true } - override fun getRestoreProgress(): Observable = restoreProgress - private fun isBackupOrRestoreRunning(): Boolean { return backupProgress.blockingFirst().running || restoreProgress.blockingFirst().running } diff --git a/data/src/main/java/com/moez/QKSMS/repository/MessageRepositoryImpl.kt b/data/src/main/java/com/moez/QKSMS/repository/MessageRepositoryImpl.kt index 7fbd3d5364060f12e5a3919f9c59aa7ddd0635cc..5ea1c773ba57693a266310775c199d8ae108703f 100644 --- a/data/src/main/java/com/moez/QKSMS/repository/MessageRepositoryImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/repository/MessageRepositoryImpl.kt @@ -26,8 +26,10 @@ import android.content.Context import android.content.Intent import android.graphics.BitmapFactory import android.media.MediaScannerConnection +import android.net.Uri import android.os.Build import android.os.Environment +import android.provider.MediaStore import android.provider.Telephony import android.provider.Telephony.Mms import android.provider.Telephony.Sms @@ -44,6 +46,8 @@ import com.klinker.android.send_message.Transaction import com.moez.QKSMS.common.util.extensions.now import com.moez.QKSMS.compat.TelephonyCompat import com.moez.QKSMS.extensions.anyOf +import com.moez.QKSMS.extensions.isImage +import com.moez.QKSMS.extensions.isVideo import com.moez.QKSMS.manager.ActiveConversationManager import com.moez.QKSMS.manager.KeyManager import com.moez.QKSMS.util.FileUtils @@ -62,6 +66,8 @@ import io.realm.Case import io.realm.Realm import io.realm.RealmResults import io.realm.Sort +import okio.buffer +import okio.source import timber.log.Timber import java.io.File import java.io.FileNotFoundException @@ -175,37 +181,53 @@ class MessageRepositoryImpl @Inject constructor( .findAllAsync() } - override fun savePart(id: Long): File? { + override fun savePart(id: Long): Uri? { val part = getPart(id) ?: return null val extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(part.type) ?: return null val date = part.messages?.first()?.date - val dir = File(MEDIA_DIRECTORY).apply { mkdirs() } - val fileName = part.name?.takeIf { name -> name.endsWith(extension) } ?: "${part.type.split("/").last()}_$date.$extension" - var file: File - var index = 0 - do { - file = File(dir, if (index == 0) fileName else fileName.replace(".$extension", " ($index).$extension")) - index++ - } while (file.exists()) - try { - FileOutputStream(file).use { outputStream -> + val values = contentValuesOf( + MediaStore.MediaColumns.DISPLAY_NAME to fileName, + MediaStore.MediaColumns.MIME_TYPE to part.type, + ) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + values.put(MediaStore.MediaColumns.IS_PENDING, 1) + values.put(MediaStore.MediaColumns.RELATIVE_PATH, when { + part.isImage() -> "${Environment.DIRECTORY_PICTURES}/Message" + part.isVideo() -> "${Environment.DIRECTORY_MOVIES}/Message" + else -> "${Environment.DIRECTORY_DOWNLOADS}/Message" + }) + } + + val contentUri = when { + part.isImage() -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI + part.isVideo() -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI + Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> MediaStore.Downloads.EXTERNAL_CONTENT_URI + else -> MediaStore.Files.getContentUri("external") + } + val resolver = context.contentResolver + val uri = resolver.insert(contentUri, values) + Timber.v("Saving $fileName (${part.type}) to $uri") + + uri?.let { + resolver.openOutputStream(uri)?.use { outputStream -> context.contentResolver.openInputStream(part.getUri())?.use { inputStream -> inputStream.copyTo(outputStream, 1024) } } - } catch (e: FileNotFoundException) { - e.printStackTrace() - } catch (e: IOException) { - e.printStackTrace() - } + Timber.v("Saved $fileName (${part.type}) to $uri") - MediaScannerConnection.scanFile(context, arrayOf(file.path), null, null) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + resolver.update(uri, contentValuesOf(MediaStore.MediaColumns.IS_PENDING to 0), null, null) + Timber.v("Marked $uri as not pending") + } + } - return file.takeIf { it.exists() } + return uri } /** @@ -328,11 +350,7 @@ class MessageRepositoryImpl @Inject constructor( val intent = getIntentForDelayedSms(message.id) val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, sendTime, intent) - } else { - alarmManager.setExact(AlarmManager.RTC_WAKEUP, sendTime, intent) - } + alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, sendTime, intent) } else { // No delay val message = insertSentSms(subId, threadId, addresses.first(), signedBody, System.currentTimeMillis()) sendSms(message) @@ -446,13 +464,13 @@ class MessageRepositoryImpl @Inject constructor( val sentIntents = parts.map { val intent = Intent(context, SmsSentReceiver::class.java).putExtra("id", message.id) - PendingIntent.getBroadcast(context, message.id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT) + PendingIntent.getBroadcast(context, message.id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) } val deliveredIntents = parts.map { val intent = Intent(context, SmsDeliveredReceiver::class.java).putExtra("id", message.id) val pendingIntent = PendingIntent - .getBroadcast(context, message.id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT) + .getBroadcast(context, message.id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) if (prefs.delivery.get()) pendingIntent else null } @@ -496,7 +514,7 @@ class MessageRepositoryImpl @Inject constructor( private fun getIntentForDelayedSms(id: Long): PendingIntent { val intent = Intent(context, SendSmsReceiver::class.java).putExtra("id", id) - return PendingIntent.getBroadcast(context, id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT) + return PendingIntent.getBroadcast(context, id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) } override fun insertSentSms(subId: Int, threadId: Long, address: String, body: String, date: Long): Message { diff --git a/data/src/main/java/com/moez/QKSMS/util/NightModeManager.kt b/data/src/main/java/com/moez/QKSMS/util/NightModeManager.kt index 8cfac4158ec9c7c9ad2b2f6d521d95af42fe16d0..317be5f884b37919c09e61188a4ba6d0bf8e4f7e 100644 --- a/data/src/main/java/com/moez/QKSMS/util/NightModeManager.kt +++ b/data/src/main/java/com/moez/QKSMS/util/NightModeManager.kt @@ -100,11 +100,11 @@ class NightModeManager @Inject constructor( private fun updateAlarms() { val dayCalendar = createCalendar(prefs.nightEnd.get()) val day = Intent(context, NightModeReceiver::class.java) - val dayIntent = PendingIntent.getBroadcast(context, 0, day, 0) + val dayIntent = PendingIntent.getBroadcast(context, 0, day, PendingIntent.FLAG_IMMUTABLE) val nightCalendar = createCalendar(prefs.nightStart.get()) val night = Intent(context, NightModeReceiver::class.java) - val nightIntent = PendingIntent.getBroadcast(context, 1, night, 0) + val nightIntent = PendingIntent.getBroadcast(context, 1, night, PendingIntent.FLAG_IMMUTABLE) context.sendBroadcast(day) context.sendBroadcast(night) diff --git a/domain/build.gradle b/domain/build.gradle index 85a69fd8daec50d7eb7add7e2bb7ba49aa72af99..90a4cfe520c49446ed2873643c79c212c659c005 100644 --- a/domain/build.gradle +++ b/domain/build.gradle @@ -23,7 +23,7 @@ apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' android { - compileSdkVersion 29 + compileSdkVersion 33 compileOptions { sourceCompatibility 1.8 @@ -31,12 +31,15 @@ android { } defaultConfig { - minSdkVersion 21 - targetSdkVersion 29 + minSdkVersion 23 + targetSdkVersion 33 } + namespace 'com.moez.QKSMS.domain' } dependencies { + // androidx + implementation "androidx.documentfile:documentfile:$androidx_documentfile_version" // dagger implementation "com.google.dagger:dagger:$dagger_version" diff --git a/domain/src/main/AndroidManifest.xml b/domain/src/main/AndroidManifest.xml index 00485b51ab90b8087876f90767e0e0d5f8b6c75d..21edd1fd3fb231816cc9f4a8c0583ce2367d42e5 100644 --- a/domain/src/main/AndroidManifest.xml +++ b/domain/src/main/AndroidManifest.xml @@ -16,4 +16,4 @@ ~ You should have received a copy of the GNU General Public License ~ along with QKSMS. If not, see . --> - + diff --git a/domain/src/main/java/com/moez/QKSMS/interactor/PerformRestore.kt b/domain/src/main/java/com/moez/QKSMS/interactor/PerformRestore.kt index 03ef3ca1988974acee3911b6ab805cccad39c520..2dfb6ce403449154ece250f32aebd76ea18f0eb3 100644 --- a/domain/src/main/java/com/moez/QKSMS/interactor/PerformRestore.kt +++ b/domain/src/main/java/com/moez/QKSMS/interactor/PerformRestore.kt @@ -18,17 +18,18 @@ */ package com.moez.QKSMS.interactor +import android.net.Uri import com.moez.QKSMS.repository.BackupRepository import io.reactivex.Flowable import javax.inject.Inject class PerformRestore @Inject constructor( private val backupRepo: BackupRepository -) : Interactor() { +) : Interactor() { - override fun buildObservable(params: String): Flowable<*> { + override fun buildObservable(params: Uri): Flowable<*> { return Flowable.just(params) .doOnNext(backupRepo::performRestore) } -} \ No newline at end of file +} diff --git a/domain/src/main/java/com/moez/QKSMS/manager/PermissionManager.kt b/domain/src/main/java/com/moez/QKSMS/manager/PermissionManager.kt index 0fd6123a9ce951fcb714fbaae5b2eb57bd1601c5..f53ea5b4710f14c5b4de9ccb5b93874e17edfd0e 100644 --- a/domain/src/main/java/com/moez/QKSMS/manager/PermissionManager.kt +++ b/domain/src/main/java/com/moez/QKSMS/manager/PermissionManager.kt @@ -28,10 +28,14 @@ interface PermissionManager { fun hasContacts(): Boolean + fun hasNotifications(): Boolean + fun hasPhone(): Boolean fun hasCalling(): Boolean fun hasStorage(): Boolean -} \ No newline at end of file + fun hasExactAlarms(): Boolean + +} diff --git a/domain/src/main/java/com/moez/QKSMS/model/BackupFile.kt b/domain/src/main/java/com/moez/QKSMS/model/BackupFile.kt index eca659216aa94badd159cf2e0bbb38423228e8b1..5de80d2106a6331b12338acec6230a24eac0fa19 100644 --- a/domain/src/main/java/com/moez/QKSMS/model/BackupFile.kt +++ b/domain/src/main/java/com/moez/QKSMS/model/BackupFile.kt @@ -19,8 +19,6 @@ package com.moez.QKSMS.model data class BackupFile( - val path: String, val date: Long, - val messages: Int, - val size: Long -) \ No newline at end of file + val messages: Int +) diff --git a/domain/src/main/java/com/moez/QKSMS/repository/BackupRepository.kt b/domain/src/main/java/com/moez/QKSMS/repository/BackupRepository.kt index 7c73a731268978db2d4113239ec3abf018a7afdf..57bc7695eb9c8928e9c52cd4af52f003943c58ca 100644 --- a/domain/src/main/java/com/moez/QKSMS/repository/BackupRepository.kt +++ b/domain/src/main/java/com/moez/QKSMS/repository/BackupRepository.kt @@ -18,6 +18,8 @@ */ package com.moez.QKSMS.repository +import android.net.Uri +import androidx.documentfile.provider.DocumentFile import com.moez.QKSMS.model.BackupFile import io.reactivex.Observable @@ -32,19 +34,24 @@ interface BackupRepository { class Finished : Progress(true, false) } + fun getDefaultBackupPath(): String + + fun getBackupDocumentTree(): DocumentFile? + + fun getBackupPathUriForPicker(): Uri + + fun persistBackupDirectory(directory: Uri) + fun performBackup() fun getBackupProgress(): Observable - /** - * Returns a list of all local backups - */ - fun getBackups(): Observable> + fun parseBackup(uri: Uri): BackupFile - fun performRestore(filePath: String) - - fun stopRestore() + fun performRestore(uri: Uri) fun getRestoreProgress(): Observable -} \ No newline at end of file + fun stopRestore() + +} diff --git a/domain/src/main/java/com/moez/QKSMS/repository/MessageRepository.kt b/domain/src/main/java/com/moez/QKSMS/repository/MessageRepository.kt index a3ef7c19fa4bf716c9d8cd56c84b6c511676d349..162f32668e5b3295dce741c56afd345bcacae938 100644 --- a/domain/src/main/java/com/moez/QKSMS/repository/MessageRepository.kt +++ b/domain/src/main/java/com/moez/QKSMS/repository/MessageRepository.kt @@ -18,6 +18,7 @@ */ package com.moez.QKSMS.repository +import android.net.Uri import com.moez.QKSMS.model.Attachment import com.moez.QKSMS.model.Message import com.moez.QKSMS.model.MmsPart @@ -40,7 +41,7 @@ interface MessageRepository { fun getPartsForConversation(threadId: Long): RealmResults - fun savePart(id: Long): File? + fun savePart(id: Long): Uri? /** * Retrieves the list of messages which should be shown in the notification diff --git a/domain/src/main/java/com/moez/QKSMS/util/Preferences.kt b/domain/src/main/java/com/moez/QKSMS/util/Preferences.kt index b9aa930324b0b283ff662c42d263523efb85b9f4..8f78461fd32840347dc72ce1b331fb4ac453ac82 100644 --- a/domain/src/main/java/com/moez/QKSMS/util/Preferences.kt +++ b/domain/src/main/java/com/moez/QKSMS/util/Preferences.kt @@ -21,6 +21,7 @@ package com.moez.QKSMS.util import android.R import android.content.Context import android.content.SharedPreferences +import android.net.Uri import android.os.Build import android.provider.Settings import android.util.TypedValue @@ -88,6 +89,8 @@ class Preferences @Inject constructor( val canUseSubId = rxPrefs.getBoolean("canUseSubId", true) val version = rxPrefs.getInteger("version", context.versionCode) val changelogVersion = rxPrefs.getInteger("changelogVersion", context.versionCode) + val hasAskedForNotificationPermission = rxPrefs.getBoolean("hasAskedForNotificationPermission", false) + val backupDirectory = rxPrefs.getObject("backupDirectory", Uri.EMPTY, UriPreferenceConverter()) @Deprecated("This should only be accessed when migrating to @blockingManager") val sia = rxPrefs.getBoolean("sia", false) diff --git a/domain/src/main/java/com/moez/QKSMS/util/UriPreferenceConverter.kt b/domain/src/main/java/com/moez/QKSMS/util/UriPreferenceConverter.kt new file mode 100644 index 0000000000000000000000000000000000000000..34142595ced18c9d04c2038b6568892c9a97a3f8 --- /dev/null +++ b/domain/src/main/java/com/moez/QKSMS/util/UriPreferenceConverter.kt @@ -0,0 +1,16 @@ +package com.moez.QKSMS.util + +import android.net.Uri +import com.f2prateek.rx.preferences2.Preference.Converter + +class UriPreferenceConverter : Converter { + + override fun deserialize(serialized: String): Uri { + return Uri.parse(serialized) + } + + override fun serialize(value: Uri): String { + return value.toString() + } + +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 024d97ff66fa95fbe24dade01f946f66d197e135..e9badb5d75905f00629ada717af2588fe74846dd 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Thu Mar 17 12:40:57 IST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip distributionPath=wrapper/dists -zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip diff --git a/presentation/build.gradle b/presentation/build.gradle index 2a12b53993f8a41e2849bc83f8960b08ae02d126..9a992db41e713e5a7fe5540f7e0139f828bedc76 100644 --- a/presentation/build.gradle +++ b/presentation/build.gradle @@ -23,16 +23,15 @@ apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' android { - compileSdkVersion 29 - buildToolsVersion "29.0.3" + compileSdkVersion 33 flavorDimensions "analytics" defaultConfig { applicationId "foundation.e.message" - minSdkVersion 21 - targetSdkVersion 29 - versionCode 2218 - versionName "3.9.4" + minSdkVersion 23 + targetSdkVersion 33 + versionCode 2220 + versionName "3.10.1" setProperty("archivesBaseName", "QKSMS-v${versionName}") testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -67,14 +66,17 @@ android { jvmTarget = "1.8" } - lintOptions { - abortOnError false - } productFlavors { withAnalytics { dimension "analytics" } noAnalytics { dimension "analytics" } } + + lint { + abortOnError false + } + namespace 'com.moez.QKSMS' + /*if (System.getenv("CI") == "true") { signingConfigs.release.storeFile = file("../keystore") signingConfigs.release.storePassword = System.getenv("keystore_password") diff --git a/presentation/src/main/AndroidManifest.xml b/presentation/src/main/AndroidManifest.xml index 690d479d08cb95e4ec6d960bc581b024e4bf9d8b..9f908b2b29f038f5fc963370f95bb3cbec202022 100644 --- a/presentation/src/main/AndroidManifest.xml +++ b/presentation/src/main/AndroidManifest.xml @@ -17,19 +17,21 @@ ~ along with QKSMS. If not, see . --> + xmlns:tools="http://schemas.android.com/tools"> + + @@ -40,13 +42,15 @@ android:name=".common.QKApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" - android:label="@string/app_name" + android:label="@string/e_app_name" + tools:replace="android:label" android:requestLegacyExternalStorage="true" android:supportsRtl="true" android:theme="@style/AppLaunchTheme"> @@ -58,6 +62,7 @@ @@ -117,12 +122,16 @@ - + - + @@ -138,6 +147,7 @@ @@ -161,13 +171,18 @@ - + + - + @@ -184,6 +199,7 @@ + @@ -204,7 +220,8 @@ @@ -230,4 +247,12 @@ + + + + + + + + diff --git a/presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt b/presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt index d6e6e1f767902776e3f25e2919f718aad0ffbec7..30d88ba1b830e95f3122c2cb0765af167225f328 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/Navigator.kt @@ -240,27 +240,33 @@ class Navigator @Inject constructor( startActivityExternal(intent) } - fun viewFile(file: File) { - val data = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", file) - val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(file.name.split(".").last()) + fun viewFile(uri: Uri, mimeType: String) { val intent = Intent(Intent.ACTION_VIEW) - .setDataAndType(data, type) + .setDataAndType(uri, mimeType.lowercase()) .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + .let { Intent.createChooser(it, null) } startActivityExternal(intent) } - fun shareFile(file: File) { - val data = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", file) - val type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(file.name.split(".").last()) + fun shareFile(uri: Uri, mimeType: String) { val intent = Intent(Intent.ACTION_SEND) - .setType(type) - .putExtra(Intent.EXTRA_STREAM, data) + .setType(mimeType.lowercase()) + .putExtra(Intent.EXTRA_STREAM, uri) .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + .let { Intent.createChooser(it, null) } startActivityExternal(intent) } + fun showPermissions() { + val intent = Intent() + intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS + intent.data = Uri.fromParts("package", context.packageName, null) + + startActivity(intent) + } + fun showNotificationSettings(threadId: Long = 0) { val intent = Intent(context, NotificationPrefsActivity::class.java) intent.putExtra("threadId", threadId) @@ -281,4 +287,12 @@ class Navigator @Inject constructor( } } -} \ No newline at end of file + fun showExactAlarmsSettings() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + val intent = Intent(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM) + .setData(Uri.parse("package:${context.packageName}")) + startActivity(intent) + } + } + +} diff --git a/presentation/src/main/java/com/moez/QKSMS/common/base/QkThemedActivity.kt b/presentation/src/main/java/com/moez/QKSMS/common/base/QkThemedActivity.kt index 14b858b2c3e63bd499750b8b899b99bcad3bac45..f0c133683cd2e84348f65cf1efcd58ed2c1edcc9 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/base/QkThemedActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/base/QkThemedActivity.kt @@ -125,7 +125,7 @@ abstract class QkThemedActivity : QkActivity() { // Set the color for the recent apps title val toolbarColor = resolveThemeColor(R.attr.colorPrimary) val icon = BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher) - val taskDesc = ActivityManager.TaskDescription(getString(R.string.app_name), icon, toolbarColor) + val taskDesc = ActivityManager.TaskDescription(getString(R.string.e_app_name), icon, toolbarColor) setTaskDescription(taskDesc) } diff --git a/presentation/src/main/java/com/moez/QKSMS/common/util/NotificationManagerImpl.kt b/presentation/src/main/java/com/moez/QKSMS/common/util/NotificationManagerImpl.kt index b40b7b4db2455ca84df0456e0157c229587ef216..2b683459beecf6e77b8177245f74cb034141a8ab 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/util/NotificationManagerImpl.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/util/NotificationManagerImpl.kt @@ -58,6 +58,7 @@ import com.moez.QKSMS.util.GlideApp import com.moez.QKSMS.util.PhoneNumberUtils import com.moez.QKSMS.util.Preferences import com.moez.QKSMS.util.tryOrNull +import timber.log.Timber import javax.inject.Inject import javax.inject.Singleton @@ -95,6 +96,11 @@ class NotificationManagerImpl @Inject constructor( return } + if (!permissions.hasNotifications()) { + Timber.w("Cannot update notification because we don't have the notification permission") + return + } + val messages = messageRepo.getUnreadUnseenMessages(threadId) // If there are no messages to be displayed, make sure that the notification is dismissed @@ -115,11 +121,11 @@ class NotificationManagerImpl @Inject constructor( val taskStackBuilder = TaskStackBuilder.create(context) .addParentStack(ComposeActivity::class.java) .addNextIntent(contentIntent) - val contentPI = taskStackBuilder.getPendingIntent(threadId.toInt(), PendingIntent.FLAG_UPDATE_CURRENT) + val contentPI = taskStackBuilder.getPendingIntent(threadId.toInt(), PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) val seenIntent = Intent(context, MarkSeenReceiver::class.java).putExtra("threadId", threadId) val seenPI = PendingIntent.getBroadcast(context, threadId.toInt(), seenIntent, - PendingIntent.FLAG_UPDATE_CURRENT) + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) // We can't store a null preference, so map it to a null Uri if the pref string is empty val ringtone = prefs.ringtone(threadId).get() @@ -212,7 +218,7 @@ class NotificationManagerImpl @Inject constructor( Preferences.NOTIFICATION_PREVIEWS_NONE -> { notification - .setContentTitle(context.getString(R.string.app_name)) + .setContentTitle(context.getString(R.string.e_app_name)) .setContentText(context.resources.getQuantityString( R.plurals.notification_new_messages, messages.size, messages.size)) } @@ -234,7 +240,7 @@ class NotificationManagerImpl @Inject constructor( Preferences.NOTIFICATION_ACTION_ARCHIVE -> { val intent = Intent(context, MarkArchivedReceiver::class.java).putExtra("threadId", threadId) val pi = PendingIntent.getBroadcast(context, threadId.toInt(), intent, - PendingIntent.FLAG_UPDATE_CURRENT) + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) NotificationCompat.Action.Builder(R.drawable.ic_archive_white_24dp, actionLabels[action], pi) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_ARCHIVE).build() } @@ -245,7 +251,7 @@ class NotificationManagerImpl @Inject constructor( .putExtra("threadId", threadId) .putExtra("messageIds", messageIds) val pi = PendingIntent.getBroadcast(context, threadId.toInt(), intent, - PendingIntent.FLAG_UPDATE_CURRENT) + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) NotificationCompat.Action.Builder(R.drawable.ic_delete_white_24dp, actionLabels[action], pi) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_DELETE).build() } @@ -253,7 +259,7 @@ class NotificationManagerImpl @Inject constructor( Preferences.NOTIFICATION_ACTION_BLOCK -> { val intent = Intent(context, BlockThreadReceiver::class.java).putExtra("threadId", threadId) val pi = PendingIntent.getBroadcast(context, threadId.toInt(), intent, - PendingIntent.FLAG_UPDATE_CURRENT) + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) NotificationCompat.Action.Builder(R.drawable.ic_block_white_24dp, actionLabels[action], pi) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MUTE).build() } @@ -261,7 +267,7 @@ class NotificationManagerImpl @Inject constructor( Preferences.NOTIFICATION_ACTION_READ -> { val intent = Intent(context, MarkReadReceiver::class.java).putExtra("threadId", threadId) val pi = PendingIntent.getBroadcast(context, threadId.toInt(), intent, - PendingIntent.FLAG_UPDATE_CURRENT) + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) NotificationCompat.Action.Builder(R.drawable.ic_check_white_24dp, actionLabels[action], pi) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ).build() } @@ -272,7 +278,7 @@ class NotificationManagerImpl @Inject constructor( } else { val intent = Intent(context, QkReplyActivity::class.java).putExtra("threadId", threadId) val pi = PendingIntent.getActivity(context, threadId.toInt(), intent, - PendingIntent.FLAG_UPDATE_CURRENT) + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) NotificationCompat.Action .Builder(R.drawable.ic_reply_white_24dp, actionLabels[action], pi) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY).build() @@ -284,7 +290,7 @@ class NotificationManagerImpl @Inject constructor( val intentAction = if (permissions.hasCalling()) Intent.ACTION_CALL else Intent.ACTION_DIAL val intent = Intent(intentAction, Uri.parse("tel:$address")) val pi = PendingIntent.getActivity(context, threadId.toInt(), intent, - PendingIntent.FLAG_UPDATE_CURRENT) + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) NotificationCompat.Action.Builder(R.drawable.ic_call_white_24dp, actionLabels[action], pi) .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_CALL).build() } @@ -338,7 +344,7 @@ class NotificationManagerImpl @Inject constructor( val taskStackBuilder = TaskStackBuilder.create(context) .addParentStack(ComposeActivity::class.java) .addNextIntent(contentIntent) - val contentPI = taskStackBuilder.getPendingIntent(threadId.toInt(), PendingIntent.FLAG_UPDATE_CURRENT) + val contentPI = taskStackBuilder.getPendingIntent(threadId.toInt(), PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) val notification = NotificationCompat.Builder(context, getChannelIdForNotification(threadId)) .setContentTitle(context.getString(R.string.notification_message_failed_title)) @@ -358,7 +364,7 @@ class NotificationManagerImpl @Inject constructor( private fun getReplyAction(threadId: Long): NotificationCompat.Action { val replyIntent = Intent(context, RemoteMessagingReceiver::class.java).putExtra("threadId", threadId) val replyPI = PendingIntent.getBroadcast(context, threadId.toInt(), replyIntent, - PendingIntent.FLAG_UPDATE_CURRENT) + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE) val title = context.resources.getStringArray(R.array.notification_actions)[ Preferences.NOTIFICATION_ACTION_REPLY] diff --git a/presentation/src/main/java/com/moez/QKSMS/common/util/QkActivityResultContracts.kt b/presentation/src/main/java/com/moez/QKSMS/common/util/QkActivityResultContracts.kt new file mode 100644 index 0000000000000000000000000000000000000000..f5018c5fa03c74135cd9340cc57e60619047f18a --- /dev/null +++ b/presentation/src/main/java/com/moez/QKSMS/common/util/QkActivityResultContracts.kt @@ -0,0 +1,40 @@ +package com.moez.QKSMS.common.util + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.net.Uri +import android.os.Build +import android.provider.DocumentsContract +import androidx.activity.result.contract.ActivityResultContract + +class QkActivityResultContracts { + + data class OpenDocumentParams( + val mimeTypes: List, + val initialUri: Uri? = null + ) + + class OpenDocument : ActivityResultContract() { + override fun createIntent(context: Context, input: OpenDocumentParams): Intent { + val intent = Intent(Intent.ACTION_OPEN_DOCUMENT) + .putExtra(Intent.EXTRA_MIME_TYPES, input.mimeTypes.toTypedArray()) + .setType("*/*") + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, input.initialUri) + } + + return intent + } + + override fun parseResult(resultCode: Int, intent: Intent?): Uri? { + if (intent == null || resultCode != Activity.RESULT_OK) { + return null + } + + return intent.data + } + } + +} diff --git a/presentation/src/main/java/com/moez/QKSMS/common/util/QkChooserTargetService.kt b/presentation/src/main/java/com/moez/QKSMS/common/util/QkChooserTargetService.kt index 13cd86b0c1f3d535ce5ec22aa16de24fb88f6e56..84e141bf7dcf121d5400fe70a5d0125f9581a4b9 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/util/QkChooserTargetService.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/util/QkChooserTargetService.kt @@ -35,7 +35,6 @@ import com.moez.QKSMS.util.GlideApp import com.moez.QKSMS.util.tryOrNull import javax.inject.Inject -@RequiresApi(Build.VERSION_CODES.M) class QkChooserTargetService : ChooserTargetService() { @Inject lateinit var conversationRepo: ConversationRepository diff --git a/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/DialogExtensions.kt b/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/DialogExtensions.kt index cf8eff109108363e05ad1c17c993898fb330e4a9..78e36667d0fe6a06b4bbca5f081e921620e77e3f 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/DialogExtensions.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/DialogExtensions.kt @@ -32,4 +32,12 @@ fun AlertDialog.Builder.setNegativeButton(@StringRes textId: Int, subject: Subje fun AlertDialog.Builder.setNeutralButton(@StringRes textId: Int, subject: Subject): AlertDialog.Builder { return setNeutralButton(textId) { _, _ -> subject.onNext(Unit) } -} \ No newline at end of file +} + +fun AlertDialog.setShowing(show: Boolean) { + if (isShowing && !show) { + dismiss() + } else if (!isShowing && show) { + show() + } +} diff --git a/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/ViewExtensions.kt b/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/ViewExtensions.kt index f2bf92d1797269741f666e9a1c1d25ebc6c92bb5..862f27b31592f32c02c91a8396c0d58afd37fd26 100644 --- a/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/ViewExtensions.kt +++ b/presentation/src/main/java/com/moez/QKSMS/common/util/extensions/ViewExtensions.kt @@ -63,9 +63,6 @@ fun ProgressBar.setTint(color: Int) { fun View.setBackgroundTint(color: Int) { // API 21 doesn't support this - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) { - background?.setColorFilter(color, PorterDuff.Mode.SRC_IN) - } backgroundTintList = ColorStateList.valueOf(color) } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupAdapter.kt deleted file mode 100644 index 038295dc663993379c988dc5c002a420abcb8800..0000000000000000000000000000000000000000 --- a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupAdapter.kt +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2017 Moez Bhatti - * - * This file is part of QKSMS. - * - * QKSMS is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * QKSMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with QKSMS. If not, see . - */ -package com.moez.QKSMS.feature.backup - -import android.content.Context -import android.text.format.Formatter -import android.view.LayoutInflater -import android.view.ViewGroup -import com.moez.QKSMS.R -import com.moez.QKSMS.common.base.FlowableAdapter -import com.moez.QKSMS.common.base.QkViewHolder -import com.moez.QKSMS.common.util.DateFormatter -import com.moez.QKSMS.model.BackupFile -import io.reactivex.subjects.PublishSubject -import io.reactivex.subjects.Subject -import kotlinx.android.synthetic.main.backup_list_item.* -import javax.inject.Inject - -class BackupAdapter @Inject constructor( - private val context: Context, - private val dateFormatter: DateFormatter -) : FlowableAdapter() { - - val backupSelected: Subject = PublishSubject.create() - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { - val layoutInflater = LayoutInflater.from(parent.context) - val view = layoutInflater.inflate(R.layout.backup_list_item, parent, false) - - return QkViewHolder(view).apply { - view.setOnClickListener { backupSelected.onNext(getItem(adapterPosition)) } - } - } - - override fun onBindViewHolder(holder: QkViewHolder, position: Int) { - val backup = getItem(position) - - val count = backup.messages - - holder.title.text = dateFormatter.getDetailedTimestamp(backup.date) - holder.messages.text = context.resources.getQuantityString(R.plurals.backup_message_count, count, count) - holder.size.text = Formatter.formatFileSize(context, backup.size) - } - -} \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupController.kt b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupController.kt index 77cd1847ddc79a97f52f93c25c8cf318ce69f36f..55b7dc0633cf076c6b8bc232785ca5192806da8f 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupController.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupController.kt @@ -18,84 +18,114 @@ */ package com.moez.QKSMS.feature.backup -import android.Manifest -import android.app.Activity +import android.content.Context import android.content.res.ColorStateList import android.graphics.Typeface +import android.net.Uri import android.view.View +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog -import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.core.view.children import androidx.core.view.isVisible import com.jakewharton.rxbinding2.view.clicks import com.moez.QKSMS.R import com.moez.QKSMS.common.base.QkController -import com.moez.QKSMS.common.util.DateFormatter +import com.moez.QKSMS.common.util.QkActivityResultContracts import com.moez.QKSMS.common.util.extensions.getLabel import com.moez.QKSMS.common.util.extensions.setBackgroundTint +import com.moez.QKSMS.common.util.extensions.setNegativeButton import com.moez.QKSMS.common.util.extensions.setPositiveButton +import com.moez.QKSMS.common.util.extensions.setShowing import com.moez.QKSMS.common.util.extensions.setTint import com.moez.QKSMS.common.widget.PreferenceView import com.moez.QKSMS.injection.appComponent -import com.moez.QKSMS.model.BackupFile import com.moez.QKSMS.repository.BackupRepository import io.reactivex.Observable import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject import kotlinx.android.synthetic.main.backup_controller.* -import kotlinx.android.synthetic.main.backup_list_dialog.view.* import kotlinx.android.synthetic.main.preference_view.view.* import javax.inject.Inject class BackupController : QkController(), BackupView { - @Inject - lateinit var adapter: BackupAdapter + @Inject override lateinit var presenter: BackupPresenter - @Inject - lateinit var dateFormatter: DateFormatter + private val selectFolderCancelSubject: Subject = PublishSubject.create() + private val selectFolderConfirmSubject: Subject = PublishSubject.create() - @Inject - override lateinit var presenter: BackupPresenter + private val restoreErrorConfirmSubject: Subject = PublishSubject.create() - private val activityVisibleSubject: Subject = PublishSubject.create() - private val confirmRestoreSubject: Subject = PublishSubject.create() - private val stopRestoreSubject: Subject = PublishSubject.create() + private val confirmRestoreCancelSubject: Subject = PublishSubject.create() + private val confirmRestoreConfirmSubject: Subject = PublishSubject.create() - private val backupFilesDialog by lazy { - val view = View.inflate(activity, R.layout.backup_list_dialog, null) - .apply { files.adapter = adapter.apply { emptyView = empty } } + private val stopRestoreConfirmSubject: Subject = PublishSubject.create() + private val stopRestoreCancelSubject: Subject = PublishSubject.create() + private val documentTreeSelectedSubject: Subject = PublishSubject.create() + private val documentSelectedSubject: Subject = PublishSubject.create() + + private val stopRestoreDialog by lazy { AlertDialog.Builder(activity!!, R.style.customAlertDialog) - .setView(view) - .setCancelable(true) + .setTitle(R.string.backup_restore_stop_title) + .setMessage(R.string.backup_restore_stop_message) + .setPositiveButton(R.string.button_stop, stopRestoreConfirmSubject) + .setNegativeButton(R.string.button_cancel, stopRestoreCancelSubject) + .setCancelable(false) .create() } - private val confirmRestoreDialog by lazy { - AlertDialog.Builder(activity!!, R.style.customAlertDialog) - .setTitle(R.string.backup_restore_confirm_title) - .setMessage(R.string.backup_restore_confirm_message) - .setPositiveButton(R.string.backup_restore_title, confirmRestoreSubject) - .setNegativeButton(R.string.button_cancel, null) + private val selectLocationRationaleDialog by lazy { + AlertDialog.Builder(activity!!) + .setTitle(R.string.backup_select_location_rationale_title) + .setMessage(R.string.backup_select_location_rationale_message) + .setPositiveButton(R.string.button_continue, selectFolderConfirmSubject) + .setNegativeButton(R.string.button_cancel, selectFolderCancelSubject) + .setCancelable(false) .create() } - private val stopRestoreDialog by lazy { - AlertDialog.Builder(activity!!, R.style.customAlertDialog) - .setTitle(R.string.backup_restore_stop_title) - .setMessage(R.string.backup_restore_stop_message) - .setPositiveButton(R.string.button_stop, stopRestoreSubject) - .setNegativeButton(R.string.button_cancel, null) + private val selectedBackupErrorDialog by lazy { + AlertDialog.Builder(activity!!) + .setTitle(R.string.backup_selected_backup_error_title) + .setMessage(R.string.backup_selected_backup_error_message) + .setPositiveButton(R.string.button_continue, restoreErrorConfirmSubject) + .setCancelable(false) + .create() + } + + private val selectedBackupDetailsDialog by lazy { + AlertDialog.Builder(activity!!) + .setTitle(R.string.backup_selected_backup_details_title) + .setPositiveButton(R.string.backup_restore_title, confirmRestoreConfirmSubject) + .setNegativeButton(R.string.button_cancel, confirmRestoreCancelSubject) + .setCancelable(false) .create() } + private lateinit var openDirectory: ActivityResultLauncher + private lateinit var openDocument: ActivityResultLauncher + init { appComponent.inject(this) layoutRes = R.layout.backup_controller } + override fun onContextAvailable(context: Context) { + // Init activity result contracts + openDirectory = themedActivity!! + .registerForActivityResult(ActivityResultContracts.OpenDocumentTree()) { uri -> + uri?.let(documentTreeSelectedSubject::onNext) + } + + openDocument = themedActivity!! + .registerForActivityResult(QkActivityResultContracts.OpenDocument()) { uri -> + uri?.let(documentSelectedSubject::onNext) + } + } + override fun onAttach(view: View) { super.onAttach(view) presenter.bindIntents(this) @@ -120,11 +150,6 @@ class BackupController : QkController( .forEach { it.setTypeface(it.typeface, Typeface.BOLD) } } - override fun onActivityResumed(activity: Activity) { - super.onActivityResumed(activity) - activityVisibleSubject.onNext(Unit) - } - override fun render(state: BackupState) { when { state.backupProgress.running -> { @@ -163,9 +188,14 @@ class BackupController : QkController( } } - backup.summary = state.lastBackup + selectLocationRationaleDialog.setShowing(state.showLocationRationale) + + selectedBackupErrorDialog.setShowing(state.showSelectedBackupError) + + selectedBackupDetailsDialog.setMessage(state.selectedBackupDetails) + selectedBackupDetailsDialog.setShowing(state.selectedBackupDetails != null) - adapter.data = state.backups + stopRestoreDialog.setShowing(state.showStopRestoreDialog) fabIcon.setImageResource(when (state.upgraded) { true -> R.drawable.ic_file_upload_black_24dp @@ -178,29 +208,40 @@ class BackupController : QkController( }) } - override fun activityVisible(): Observable<*> = activityVisibleSubject + override fun setBackupLocationClicks(): Observable<*> = location.clicks() override fun restoreClicks(): Observable<*> = restore.clicks() - override fun restoreFileSelected(): Observable = adapter.backupSelected - .doOnNext { backupFilesDialog.dismiss() } + override fun locationRationaleConfirmClicks(): Observable<*> = selectFolderConfirmSubject - override fun restoreConfirmed(): Observable<*> = confirmRestoreSubject + override fun locationRationaleCancelClicks(): Observable<*> = selectFolderCancelSubject + + override fun selectedBackupErrorClicks(): Observable<*> = restoreErrorConfirmSubject + + override fun confirmRestoreBackupConfirmClicks(): Observable<*> = confirmRestoreConfirmSubject + + override fun confirmRestoreBackupCancelClicks(): Observable<*> = confirmRestoreCancelSubject override fun stopRestoreClicks(): Observable<*> = progressCancel.clicks() - override fun stopRestoreConfirmed(): Observable<*> = stopRestoreSubject + override fun stopRestoreConfirmed(): Observable<*> = stopRestoreConfirmSubject - override fun fabClicks(): Observable<*> = fab.clicks() + override fun stopRestoreCancel(): Observable<*> = stopRestoreCancelSubject - override fun requestStoragePermission() { - ActivityCompat.requestPermissions(activity!!, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 0) - } + override fun backupClicks(): Observable<*> = fab.clicks() - override fun selectFile() = backupFilesDialog.show() + override fun documentTreeSelected(): Observable = documentTreeSelectedSubject - override fun confirmRestore() = confirmRestoreDialog.show() + override fun documentSelected(): Observable = documentSelectedSubject - override fun stopRestore() = stopRestoreDialog.show() + override fun selectFolder(initialUri: Uri) { + openDirectory.launch(initialUri) + } + + override fun selectFile(initialUri: Uri) { + openDocument.launch(QkActivityResultContracts.OpenDocumentParams( + mimeTypes = listOf("application/json", "application/octet-stream"), + initialUri = initialUri)) + } } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupPresenter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupPresenter.kt index 09f5aa1621f50e12f6845c58e403823afe122670..ee706c64911c72abafbb3ee3e6fbd4c6c3d619de 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupPresenter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupPresenter.kt @@ -19,6 +19,7 @@ package com.moez.QKSMS.feature.backup import android.content.Context +import androidx.core.net.toUri import com.moez.QKSMS.R import com.moez.QKSMS.common.Navigator import com.moez.QKSMS.common.base.QkPresenter @@ -26,14 +27,14 @@ import com.moez.QKSMS.common.util.DateFormatter import com.moez.QKSMS.common.util.extensions.makeToast import com.moez.QKSMS.interactor.PerformBackup import com.moez.QKSMS.manager.BillingManager -import com.moez.QKSMS.manager.PermissionManager import com.moez.QKSMS.repository.BackupRepository import com.uber.autodispose.android.lifecycle.scope import com.uber.autodispose.autoDisposable +import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.rxkotlin.plusAssign import io.reactivex.rxkotlin.withLatestFrom -import io.reactivex.subjects.BehaviorSubject -import io.reactivex.subjects.Subject +import io.reactivex.schedulers.Schedulers +import timber.log.Timber import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -43,12 +44,9 @@ class BackupPresenter @Inject constructor( private val context: Context, private val dateFormatter: DateFormatter, private val navigator: Navigator, - private val performBackup: PerformBackup, - private val permissionManager: PermissionManager + private val performBackup: PerformBackup ) : QkPresenter(BackupState()) { - private val storagePermissionSubject: Subject = BehaviorSubject.createDefault(permissionManager.hasStorage()) - init { disposables += backupRepo.getBackupProgress() .sample(16, TimeUnit.MILLISECONDS) @@ -60,20 +58,6 @@ class BackupPresenter @Inject constructor( .distinctUntilChanged() .subscribe { progress -> newState { copy(restoreProgress = progress) } } - disposables += storagePermissionSubject - .distinctUntilChanged() - .switchMap { backupRepo.getBackups() } - .doOnNext { backups -> newState { copy(backups = backups) } } - .map { backups -> backups.map { it.date }.max() ?: 0L } - .map { lastBackup -> - when (lastBackup) { - 0L -> context.getString(R.string.backup_never) - else -> dateFormatter.getDetailedTimestamp(lastBackup) - } - } - .startWith(context.getString(R.string.backup_loading)) - .subscribe { lastBackup -> newState { copy(lastBackup = lastBackup) } } - disposables += billingManager.upgradeStatus .subscribe { upgraded -> newState { copy(upgraded = upgraded) } } } @@ -81,10 +65,10 @@ class BackupPresenter @Inject constructor( override fun bindIntents(view: BackupView) { super.bindIntents(view) - view.activityVisible() - .map { permissionManager.hasStorage() } + view.setBackupLocationClicks() + .observeOn(AndroidSchedulers.mainThread()) .autoDisposable(view.scope()) - .subscribe(storagePermissionSubject) + .subscribe { view.selectFolder(backupRepo.getBackupPathUriForPicker()) } view.restoreClicks() .withLatestFrom( @@ -96,38 +80,78 @@ class BackupPresenter @Inject constructor( !upgraded -> context.makeToast(R.string.backup_restore_error_plus) backupProgress.running -> context.makeToast(R.string.backup_restore_error_backup) restoreProgress.running -> context.makeToast(R.string.backup_restore_error_restore) - !permissionManager.hasStorage() -> view.requestStoragePermission() - else -> view.selectFile() + else -> view.selectFile(backupRepo.getBackupPathUriForPicker()) } } .autoDisposable(view.scope()) .subscribe() - view.restoreFileSelected() + view.backupClicks() + .withLatestFrom(billingManager.upgradeStatus) { _, upgraded -> upgraded } + .autoDisposable(view.scope()) + .subscribe { upgraded -> + when { + backupRepo.getBackupDocumentTree() == null -> { + newState { copy(showLocationRationale = true) } + } + !upgraded -> navigator.showQksmsPlusActivity("backup_fab") + upgraded -> performBackup.execute(Unit) + } + } + + view.locationRationaleConfirmClicks() + .doOnNext { newState { copy(showLocationRationale = false) } } .autoDisposable(view.scope()) - .subscribe { view.confirmRestore() } + .subscribe { view.selectFolder(backupRepo.getBackupPathUriForPicker()) } - view.restoreConfirmed() - .withLatestFrom(view.restoreFileSelected()) { _, backup -> backup } + view.locationRationaleCancelClicks() + .doOnNext { newState { copy(showLocationRationale = false) } } .autoDisposable(view.scope()) - .subscribe { backup -> RestoreBackupService.start(context, backup.path) } + .subscribe() + + view.selectedBackupErrorClicks() + .autoDisposable(view.scope()) + .subscribe { newState { copy(showSelectedBackupError = false) } } + + view.confirmRestoreBackupConfirmClicks() + .doOnNext { newState { copy(selectedBackupDetails = null) } } + .withLatestFrom(view.documentSelected()) { _, backup -> backup } + .autoDisposable(view.scope()) + .subscribe { backup -> RestoreBackupService.start(context, backup) } + + view.confirmRestoreBackupCancelClicks() + .doOnNext { newState { copy(selectedBackupDetails = null) } } + .autoDisposable(view.scope()) + .subscribe() view.stopRestoreClicks() .autoDisposable(view.scope()) - .subscribe { view.stopRestore() } + .subscribe { newState { copy(showStopRestoreDialog = true) } } view.stopRestoreConfirmed() + .doOnNext { newState { copy(showStopRestoreDialog = false) } } .autoDisposable(view.scope()) .subscribe { backupRepo.stopRestore() } - view.fabClicks() - .withLatestFrom(billingManager.upgradeStatus) { _, upgraded -> upgraded } + view.stopRestoreCancel() .autoDisposable(view.scope()) - .subscribe { upgraded -> - when { - !upgraded -> navigator.showQksmsPlusActivity("backup_fab") - !permissionManager.hasStorage() -> view.requestStoragePermission() - upgraded -> performBackup.execute(Unit) + .subscribe { newState { copy(showStopRestoreDialog = false) } } + + view.documentTreeSelected() + .autoDisposable(view.scope()) + .subscribe { uri -> backupRepo.persistBackupDirectory(uri) } + + view.documentSelected() + .observeOn(Schedulers.io()) + .autoDisposable(view.scope()) + .subscribe { uri -> + try { + val backupFile = backupRepo.parseBackup(uri) + val date = dateFormatter.getDetailedTimestamp(backupFile.date) + val details = context.getString(R.string.backup_details, date, backupFile.messages) + newState { copy(selectedBackupDetails = details) } + } catch (e: Exception) { + newState { copy(showSelectedBackupError = true) } } } } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupState.kt b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupState.kt index b658581039ea7928552dc561947597d99c4268cc..c64a1afda7a24d091f2deb8f64d8bd8811ca2864 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupState.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupState.kt @@ -18,13 +18,16 @@ */ package com.moez.QKSMS.feature.backup -import com.moez.QKSMS.model.BackupFile import com.moez.QKSMS.repository.BackupRepository data class BackupState( val backupProgress: BackupRepository.Progress = BackupRepository.Progress.Idle(), val restoreProgress: BackupRepository.Progress = BackupRepository.Progress.Idle(), - val lastBackup: String = "", - val backups: List = listOf(), + + val showLocationRationale: Boolean = false, + val showSelectedBackupError: Boolean = false, + val selectedBackupDetails: String? = null, + val showStopRestoreDialog: Boolean = false, + val upgraded: Boolean = false -) \ No newline at end of file +) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupView.kt b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupView.kt index abef9b0e664fe60dbb6061d3d8043b02d8423434..b19ddf578d4a777736d51de4eeca97e71f0e16ec 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupView.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/backup/BackupView.kt @@ -18,23 +18,31 @@ */ package com.moez.QKSMS.feature.backup +import android.net.Uri import com.moez.QKSMS.common.base.QkViewContract -import com.moez.QKSMS.model.BackupFile import io.reactivex.Observable interface BackupView : QkViewContract { - - fun activityVisible(): Observable<*> + fun setBackupLocationClicks(): Observable<*> fun restoreClicks(): Observable<*> - fun restoreFileSelected(): Observable - fun restoreConfirmed(): Observable<*> + + fun backupClicks(): Observable<*> + + fun locationRationaleConfirmClicks(): Observable<*> + fun locationRationaleCancelClicks(): Observable<*> + + fun selectedBackupErrorClicks(): Observable<*> + + fun confirmRestoreBackupConfirmClicks(): Observable<*> + fun confirmRestoreBackupCancelClicks(): Observable<*> + fun stopRestoreClicks(): Observable<*> fun stopRestoreConfirmed(): Observable<*> - fun fabClicks(): Observable<*> + fun stopRestoreCancel(): Observable<*> - fun requestStoragePermission() - fun selectFile() - fun confirmRestore() - fun stopRestore() + fun documentTreeSelected(): Observable + fun documentSelected(): Observable -} \ No newline at end of file + fun selectFolder(initialUri: Uri) + fun selectFile(initialUri: Uri) +} diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/backup/RestoreBackupService.kt b/presentation/src/main/java/com/moez/QKSMS/feature/backup/RestoreBackupService.kt index 49527ef0f45e2f6b503e4f4a38b25aa08d229411..a7d059e57dafba474166202c904d9a4d4fb5347e 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/backup/RestoreBackupService.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/backup/RestoreBackupService.kt @@ -22,6 +22,7 @@ import android.annotation.SuppressLint import android.app.Service import android.content.Context import android.content.Intent +import android.net.Uri import android.os.IBinder import androidx.core.app.NotificationManagerCompat import androidx.core.content.ContextCompat @@ -43,12 +44,12 @@ class RestoreBackupService : Service() { private const val ACTION_START = "com.moez.QKSMS.ACTION_START" private const val ACTION_STOP = "com.moez.QKSMS.ACTION_STOP" - private const val EXTRA_FILE_PATH = "com.moez.QKSMS.EXTRA_FILE_PATH" + private const val EXTRA_FILE_URI = "com.moez.QKSMS.EXTRA_FILE_URI" - fun start(context: Context, filePath: String) { + fun start(context: Context, backupFile: Uri) { val intent = Intent(context, RestoreBackupService::class.java) .setAction(ACTION_START) - .putExtra(EXTRA_FILE_PATH, filePath) + .putExtra(EXTRA_FILE_URI, backupFile.toString()) ContextCompat.startForegroundService(context, intent) } @@ -100,7 +101,7 @@ class RestoreBackupService : Service() { // Start the restore Observable.just(intent) - .map { it.getStringExtra(EXTRA_FILE_PATH) } + .map { Uri.parse(it.getStringExtra(EXTRA_FILE_URI)) } .map(backupRepo::performRestore) .subscribeOn(Schedulers.io()) .subscribe({}, Timber::w) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingDialog.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingDialog.kt index d70162d1ae8e7d9525971d610410d2443a0184ea..2edf62d4d073a67e45e49177badbb306e14402cd 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingDialog.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingDialog.kt @@ -95,7 +95,7 @@ class BlockingDialog @Inject constructor( Preferences.BLOCKING_MANAGER_CB -> R.string.blocking_manager_call_blocker_title Preferences.BLOCKING_MANAGER_CC -> R.string.blocking_manager_call_control_title Preferences.BLOCKING_MANAGER_SIA -> R.string.blocking_manager_sia_title - else -> R.string.blocking_manager_qksms_title + else -> R.string.e_blocking_manager_qksms_title }) val message = context.resources.getQuantityString(res, addresses.size, manager) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingPresenter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingPresenter.kt index 4e37d238c2c5b7c090fc0e73ee1848d56e7e5d24..ce2ea5fa849a51cf1eb4461147ec02c67e328acb 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingPresenter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocking/BlockingPresenter.kt @@ -41,7 +41,7 @@ class BlockingPresenter @Inject constructor( Preferences.BLOCKING_MANAGER_CB -> R.string.blocking_manager_call_blocker_title Preferences.BLOCKING_MANAGER_CC -> R.string.blocking_manager_call_control_title Preferences.BLOCKING_MANAGER_SIA -> R.string.blocking_manager_sia_title - else -> R.string.blocking_manager_qksms_title + else -> R.string.e_blocking_manager_qksms_title } } .map(context::getString) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt index 058898b8d8b244a1a0a22ecf3e335ee1fbf3de01..a77ba7c39a54959f1fae336e5c0a6bb9ad81943a 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeActivity.kt @@ -155,11 +155,6 @@ class ComposeActivity : QkThemedActivity(), ComposeView { .subscribe() window.callback = ComposeWindowCallback(window.callback, this) - - // These theme attributes don't apply themselves on API 21 - if (Build.VERSION.SDK_INT <= 22) { - messageBackground.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor)) - } } override fun onStart() { @@ -392,8 +387,8 @@ class ComposeActivity : QkThemedActivity(), ComposeView { super.onSaveInstanceState(outState) } - override fun onRestoreInstanceState(savedInstanceState: Bundle?) { - cameraDestination = savedInstanceState?.getParcelable(CameraDestinationKey) + override fun onRestoreInstanceState(savedInstanceState: Bundle) { + cameraDestination = savedInstanceState.getParcelable(CameraDestinationKey) super.onRestoreInstanceState(savedInstanceState) } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt index 28ab8e4e5ffead2671ce1ead2f4b81cbaaa718cc..083763e709bd312c4597126c7b9d19bbf81fe388 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt @@ -433,7 +433,7 @@ class ComposeViewModel @Inject constructor( .autoDisposable(view.scope()) .subscribe { part -> if (permissionManager.hasStorage()) { - messageRepo.savePart(part.id)?.let(navigator::viewFile) + messageRepo.savePart(part.id)?.let { navigator.viewFile(it, part.type) } } else { view.requestStoragePermission() } @@ -634,23 +634,36 @@ class ComposeViewModel @Inject constructor( // Send a message when the send button is clicked, and disable editing mode if it's enabled view.sendIntent - .filter { permissionManager.isDefaultSms().also { if (!it) view.requestDefaultSms() } } - .filter { permissionManager.hasSendSms().also { if (!it) view.requestSmsPermission() } } - .withLatestFrom(view.textChangedIntent) { _, body -> body } - .map { body -> body.toString() } + .withLatestFrom(view.textChangedIntent) { _, body -> body.toString() } .withLatestFrom(state, attachments, conversation, selectedChips) { body, state, attachments, conversation, chips -> - val subId = state.subscription?.subscriptionId ?: -1 - val addresses = when (conversation.recipients.isNotEmpty()) { - true -> conversation.recipients.map { it.address } - false -> chips.map { chip -> chip.address } + if (!permissionManager.isDefaultSms()) { + view.requestDefaultSms() + return@withLatestFrom + } + + if (!permissionManager.hasSendSms()) { + view.requestSmsPermission() + return@withLatestFrom } + val delay = when (prefs.sendDelay.get()) { Preferences.SEND_DELAY_SHORT -> 3000 Preferences.SEND_DELAY_MEDIUM -> 5000 Preferences.SEND_DELAY_LONG -> 10000 else -> 0 } + + if ((delay != 0 || state.scheduled != 0L) && !permissionManager.hasExactAlarms()) { + navigator.showExactAlarmsSettings() + return@withLatestFrom + } + + val subId = state.subscription?.subscriptionId ?: -1 + val addresses = when (conversation.recipients.isNotEmpty()) { + true -> conversation.recipients.map { it.address } + false -> chips.map { chip -> chip.address } + } val sendAsGroup = !state.editingMode || state.sendAsGroup when { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeWindowCallback.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeWindowCallback.kt index fbfc33b3efb6863ce4573b408271fbe1066b211a..c0924a3ee9830b1d970de1cbe8eff5b3b8deaec0 100755 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeWindowCallback.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeWindowCallback.kt @@ -123,7 +123,6 @@ class ComposeWindowCallback( return localCallback.onSearchRequested() } - @RequiresApi(api = Build.VERSION_CODES.M) override fun onSearchRequested(searchEvent: SearchEvent): Boolean { return localCallback.onSearchRequested(searchEvent) } @@ -132,7 +131,6 @@ class ComposeWindowCallback( return localCallback.onWindowStartingActionMode(callback) } - @RequiresApi(api = Build.VERSION_CODES.M) override fun onWindowStartingActionMode(callback: ActionMode.Callback, i: Int): ActionMode? { return localCallback.onWindowStartingActionMode(callback, i) } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/MessagesAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/MessagesAdapter.kt index e15991f58239629d513c9e463c0af86563adaa4a..0d8a3faf983f93db5088c6db4a50c281b0f08cf4 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/MessagesAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/MessagesAdapter.kt @@ -152,9 +152,7 @@ class MessagesAdapter @Inject constructor( view = layoutInflater.inflate(R.layout.message_list_item_in, parent, false) } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - view.body.hyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE - } + view.body.hyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE val partsAdapter = partsAdapterProvider.get() partsAdapter.clicks.subscribe(partClicks) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/ChipsAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/ChipsAdapter.kt index b415d32f377e8583b322ee85a35c9423b690f635..b81a1a980cf7c9e1f868dc6e1a06751104fc8fc2 100755 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/ChipsAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/ChipsAdapter.kt @@ -44,11 +44,6 @@ class ChipsAdapter @Inject constructor() : QkAdapter() { val inflater = LayoutInflater.from(parent.context) val view = inflater.inflate(R.layout.contact_chip, parent, false) return QkViewHolder(view).apply { - // These theme attributes don't apply themselves on API 21 - if (Build.VERSION.SDK_INT <= 22) { - content.setBackgroundTint(view.context.resolveThemeColor(R.attr.bubbleColor)) - } - view.setOnClickListener { val chip = getItem(adapterPosition) showDetailedChip(view.context, chip) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/contacts/ContactsActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/contacts/ContactsActivity.kt index f5ca9f71d41880a2451717d1bfcc8354485b491a..58f1db08d8752b15ddea3b78725c0e2902d9e38a 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/contacts/ContactsActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/contacts/ContactsActivity.kt @@ -88,11 +88,6 @@ class ContactsActivity : QkThemedActivity(), ContactsContract { viewModel.bindView(this) contacts.adapter = contactsAdapter - - // These theme attributes don't apply themselves on API 21 - if (Build.VERSION.SDK_INT <= 22) { - search.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor)) - } } override fun render(state: ContactsState) { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/gallery/GalleryViewModel.kt b/presentation/src/main/java/com/moez/QKSMS/feature/gallery/GalleryViewModel.kt index 20fb0a7cb5690345904c434e53ad647216534499..9487b1439c51ee6716b196253980a3b196012e1b 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/gallery/GalleryViewModel.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/gallery/GalleryViewModel.kt @@ -81,9 +81,11 @@ class GalleryViewModel @Inject constructor( view.optionsItemSelected() .filter { itemId -> itemId == R.id.share } .filter { permissions.hasStorage().also { if (!it) view.requestStoragePermission() } } - .withLatestFrom(view.pageChanged()) { _, part -> part.id } + .withLatestFrom(view.pageChanged()) { _, part -> part } .autoDisposable(view.scope()) - .subscribe { partId -> messageRepo.savePart(partId)?.let(navigator::shareFile) } + .subscribe { part -> + messageRepo.savePart(part.id)?.let { navigator.shareFile(it, part.type) } + } } } \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt index aad641a4f3a48bcddac19fde8725d075d4669936..5aeb46a63a9b394752a410da489079a109c90e56 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainActivity.kt @@ -177,11 +177,6 @@ class MainActivity : QkThemedActivity(), MainView { } - // These theme attributes don't apply themselves on API 21 - if (Build.VERSION.SDK_INT <= 22) { - toolbarSearch.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor)) - } - val sharedPreferences: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) val editor: SharedPreferences.Editor = sharedPreferences.edit() @@ -299,7 +294,7 @@ class MainActivity : QkThemedActivity(), MainView { when (state.syncing) { is SyncRepository.SyncProgress.Idle -> { syncing.isVisible = false - snackbar.isVisible = !state.defaultSms || !state.smsPermission || !state.contactPermission + snackbar.isVisible = !state.defaultSms || !state.smsPermission || !state.contactPermission || !state.notificationPermission } is SyncRepository.SyncProgress.Running -> { @@ -314,19 +309,25 @@ class MainActivity : QkThemedActivity(), MainView { when { !state.defaultSms -> { snackbarTitle?.setText(R.string.main_default_sms_title) - snackbarMessage?.setText(R.string.main_default_sms_message) + snackbarMessage?.setText(R.string.e_main_default_sms_message) snackbarButton?.setText(R.string.main_default_sms_change) } !state.smsPermission -> { snackbarTitle?.setText(R.string.main_permission_required) - snackbarMessage?.setText(R.string.main_permission_sms) + snackbarMessage?.setText(R.string.e_main_permission_sms) snackbarButton?.setText(R.string.main_permission_allow) } !state.contactPermission -> { snackbarTitle?.setText(R.string.main_permission_required) - snackbarMessage?.setText(R.string.main_permission_contacts) + snackbarMessage?.setText(R.string.e_main_permission_contacts) + snackbarButton?.setText(R.string.main_permission_allow) + } + + !state.notificationPermission -> { + snackbarTitle?.setText(R.string.main_permission_required) + snackbarMessage?.setText(R.string.main_permission_notifications) snackbarButton?.setText(R.string.main_permission_allow) } } @@ -360,10 +361,17 @@ class MainActivity : QkThemedActivity(), MainView { } override fun requestPermissions() { - ActivityCompat.requestPermissions(this, arrayOf( - Manifest.permission.READ_SMS, - Manifest.permission.SEND_SMS, - Manifest.permission.READ_CONTACTS), 0) + val permissions = mutableListOf( + Manifest.permission.READ_SMS, + Manifest.permission.SEND_SMS, + Manifest.permission.READ_CONTACTS + ) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + permissions += Manifest.permission.POST_NOTIFICATIONS + } + + ActivityCompat.requestPermissions(this, permissions.toTypedArray(), 0) } override fun clearSearch() { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainState.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainState.kt index 9da85458eb3aabb1260a1b05df7d9db193b3447b..1015e7d2b7adca8d403d4c2c70f11a24d32a62c5 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainState.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainState.kt @@ -32,7 +32,8 @@ data class MainState( val syncing: SyncRepository.SyncProgress = SyncRepository.SyncProgress.Idle, val defaultSms: Boolean = true, val smsPermission: Boolean = true, - val contactPermission: Boolean = true + val contactPermission: Boolean = true, + val notificationPermission: Boolean = true, ) sealed class MainPage diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt index 3ffcae9df74a53c9f65f279d8fec6acd69200044..a4571d229756a2b0f4656b9b187a5c426030322e 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/main/MainViewModel.kt @@ -18,6 +18,9 @@ */ package com.moez.QKSMS.feature.main +import android.content.Intent +import android.net.Uri +import android.provider.Settings import androidx.recyclerview.widget.ItemTouchHelper import com.moez.QKSMS.R import com.moez.QKSMS.common.Navigator @@ -135,28 +138,56 @@ class MainViewModel @Inject constructor( !permissionManager.hasReadSms() || !permissionManager.hasContacts() -> view.requestPermissions() } - val permissions = view.activityResumedIntent - .filter { resumed -> resumed } - .observeOn(Schedulers.io()) - .map { Triple(permissionManager.isDefaultSms(), permissionManager.hasReadSms(), permissionManager.hasContacts()) } - .distinctUntilChanged() - .share() - - // If the default SMS state or permission states change, update the ViewState - permissions - .doOnNext { (defaultSms, smsPermission, contactPermission) -> - newState { copy(defaultSms = defaultSms, smsPermission = smsPermission, contactPermission = contactPermission) } - } - .autoDisposable(view.scope()) - .subscribe() - - // If we go from not having all permissions to having them, sync messages - permissions - .skip(1) - .filter { it.first && it.second && it.third } - .take(1) - .autoDisposable(view.scope()) - .subscribe { syncMessages.execute(Unit) } + // If the default SMS state changes, reflect it in the State + view.activityResumedIntent + .filter { resumed -> resumed } + .observeOn(Schedulers.io()) + .map { permissionManager.isDefaultSms() } + .distinctUntilChanged() + .doOnNext { defaultSms -> newState { copy(defaultSms = defaultSms) } } + .autoDisposable(view.scope()) + .subscribe() + + // If the SMS Permission state changes, reflect it in the State + view.activityResumedIntent + .filter { resumed -> resumed } + .observeOn(Schedulers.io()) + .map { permissionManager.hasReadSms() } + .distinctUntilChanged() + .doOnNext { smsPermission -> newState { copy(smsPermission = smsPermission) } } + .autoDisposable(view.scope()) + .subscribe() + + // If the Contacts Permission state changes, reflect it in the State + view.activityResumedIntent + .filter { resumed -> resumed } + .observeOn(Schedulers.io()) + .map { permissionManager.hasContacts() } + .distinctUntilChanged() + .doOnNext { contactPermission -> newState { copy(contactPermission = contactPermission) } } + .autoDisposable(view.scope()) + .subscribe() + + // If the Notifications Permission state changes, reflect it in the State + view.activityResumedIntent + .filter { resumed -> resumed } + .observeOn(Schedulers.io()) + .map { permissionManager.hasNotifications() } + .distinctUntilChanged() + .doOnNext { notificationPermission -> newState { copy(notificationPermission = notificationPermission) } } + .autoDisposable(view.scope()) + .subscribe() + + // If we go from not having all SMS permissions to having them, sync messages + view.activityResumedIntent + .filter { resumed -> resumed } + .observeOn(Schedulers.io()) + .map { permissionManager.isDefaultSms() && permissionManager.hasReadSms() && permissionManager.hasContacts() } + .distinctUntilChanged() + .skip(1) + .filter { hasAllPermissions -> hasAllPermissions } + .autoDisposable(view.scope()) + .subscribe { syncMessages.execute(Unit) } // Launch screen from intent view.onNewIntentIntent @@ -387,6 +418,8 @@ class MainViewModel @Inject constructor( val page = state.page.copy(addContact = add, markPinned = pin, markRead = read, selected = selected) newState { copy(page = page) } } + + is Searching -> {} // Ignore } } .autoDisposable(view.scope()) @@ -425,6 +458,14 @@ class MainViewModel @Inject constructor( !state.defaultSms -> view.requestDefaultSms() !state.smsPermission -> view.requestPermissions() !state.contactPermission -> view.requestPermissions() + !state.notificationPermission -> { + if (prefs.hasAskedForNotificationPermission.get()) { + navigator.showPermissions() + } else { + prefs.hasAskedForNotificationPermission.set(true) + view.requestPermissions() + } + } } } .autoDisposable(view.scope()) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/plus/experiment/UpgradeButtonExperiment.kt b/presentation/src/main/java/com/moez/QKSMS/feature/plus/experiment/UpgradeButtonExperiment.kt index c954a5592e9002dc061cdf362cf4c14acaf87182..e5727c0c4a852a56d4b24b41c8d4281035f91e5c 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/plus/experiment/UpgradeButtonExperiment.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/plus/experiment/UpgradeButtonExperiment.kt @@ -29,7 +29,7 @@ import javax.inject.Inject class UpgradeButtonExperiment @Inject constructor( context: Context, analytics: AnalyticsManager -) : Experiment<@StringRes Int>(context, analytics) { +) : Experiment(context, analytics) { override val key: String = "Upgrade Button" diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/qkreply/QkReplyActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/qkreply/QkReplyActivity.kt index 91d1e624596186a991cdeb9714548148e713d662..9287ae9cb5717e227a779eb29d42d7bbe8fdb87a 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/qkreply/QkReplyActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/qkreply/QkReplyActivity.kt @@ -74,15 +74,6 @@ class QkReplyActivity : QkThemedActivity(), QkReplyView { messages.adapter?.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { override fun onChanged() = messages.scrollToPosition(adapter.itemCount - 1) }) - - // These theme attributes don't apply themselves on API 21 - if (Build.VERSION.SDK_INT <= 22) { - toolbar.setBackgroundTint(resolveThemeColor(R.attr.colorPrimary)) - background.setBackgroundTint(resolveThemeColor(android.R.attr.windowBackground)) - messageBackground.setBackgroundTint(resolveThemeColor(R.attr.bubbleColor)) - composeBackgroundGradient.setBackgroundTint(resolveThemeColor(android.R.attr.windowBackground)) - composeBackgroundSolid.setBackgroundTint(resolveThemeColor(android.R.attr.windowBackground)) - } } override fun render(state: QkReplyState) { diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/widget/WidgetProvider.kt b/presentation/src/main/java/com/moez/QKSMS/feature/widget/WidgetProvider.kt index 6864d0d704280b57691703ebbb1e4245e5c566e9..c8dc14a0dfd3be1af75eebd684188e7937b18b37 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/widget/WidgetProvider.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/widget/WidgetProvider.kt @@ -140,17 +140,17 @@ class WidgetProvider : AppWidgetProvider() { // Main intent val mainIntent = Intent(context, MainActivity::class.java) - val mainPI = PendingIntent.getActivity(context, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT) + val mainPI = PendingIntent.getActivity(context, 0, mainIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) remoteViews.setOnClickPendingIntent(R.id.title, mainPI) // Compose intent val composeIntent = Intent(context, ComposeActivity::class.java) - val composePI = PendingIntent.getActivity(context, 0, composeIntent, PendingIntent.FLAG_UPDATE_CURRENT) + val composePI = PendingIntent.getActivity(context, 0, composeIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) remoteViews.setOnClickPendingIntent(R.id.compose, composePI) // Conversation intent val startActivityIntent = Intent(context, MainActivity::class.java) - val startActivityPendingIntent = PendingIntent.getActivity(context, 0, startActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT) + val startActivityPendingIntent = PendingIntent.getActivity(context, 0, startActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) remoteViews.setPendingIntentTemplate(R.id.conversations, startActivityPendingIntent) AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId, remoteViews) diff --git a/presentation/src/main/res/drawable/ic_baseline_folder_24.xml b/presentation/src/main/res/drawable/ic_baseline_folder_24.xml new file mode 100644 index 0000000000000000000000000000000000000000..5e930a2f7b17de5fdfa7ea28ad712da5aa8271f4 --- /dev/null +++ b/presentation/src/main/res/drawable/ic_baseline_folder_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/presentation/src/main/res/layout/about_controller.xml b/presentation/src/main/res/layout/about_controller.xml index dc241cd15e954b9f1f39644f1eb85ca3fc63c901..f0e032d5d5a30adee92fb42281ebf82cb7e3ff4c 100644 --- a/presentation/src/main/res/layout/about_controller.xml +++ b/presentation/src/main/res/layout/about_controller.xml @@ -32,24 +32,24 @@ android:paddingBottom="8dp"> + app:summary="@string/e_app_info" + app:title="@string/e_app_info_title" /> + app:title="@string/e_app_version_title" /> + app:title="@string/e_about_fork_title" /> + app:summary="@string/e_about_author" + app:title="@string/e_about_author_title" /> + app:title="@string/e_about_privacy_title" /> + app:title="@string/e_about_terms_title" /> + app:icon="@drawable/ic_baseline_folder_24" + app:title="@string/backup_location_title" + app:summary="@string/backup_location_summary" /> diff --git a/presentation/src/main/res/layout/blocking_controller.xml b/presentation/src/main/res/layout/blocking_controller.xml index 5602fc9dfc9eb83f79a331891e973e7576fe4ff9..d340e843c379cca2dc2f37e5c6ddf8ff5c20ec1f 100644 --- a/presentation/src/main/res/layout/blocking_controller.xml +++ b/presentation/src/main/res/layout/blocking_controller.xml @@ -38,7 +38,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:title="@string/blocking_manager_title" - tools:summary="@string/blocking_manager_qksms_title" /> + tools:summary="@string/e_blocking_manager_qksms_title" /> + app:title="@string/e_settings_about_title"/> diff --git a/presentation/src/main/res/layout/widget.xml b/presentation/src/main/res/layout/widget.xml index 5e99fa8f7e0f86bbb92f043d442a340894ab73e2..a8e586ed83cd6b4ff1ffcd040757a4fbe2479444 100644 --- a/presentation/src/main/res/layout/widget.xml +++ b/presentation/src/main/res/layout/widget.xml @@ -48,7 +48,7 @@ android:gravity="center_vertical" android:paddingStart="16dp" android:paddingEnd="16dp" - android:text="@string/app_name" + android:text="@string/e_app_name" android:textSize="18sp" tools:textColor="@color/textPrimary" /> diff --git a/presentation/src/main/res/values-ar/e_strings.xml b/presentation/src/main/res/values-ar/e_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..876ac2dcdead4782adcf00d88f7077095877691b --- /dev/null +++ b/presentation/src/main/res/values-ar/e_strings.xml @@ -0,0 +1,25 @@ + + + + رسالة + جعل Message تطبيق الرسائل النصية الافتراضي لديك + معلومات الرسالة + نسخة التطبيق + سياسة الخصوصية + شروط الخدمة + المؤلفون + \ No newline at end of file diff --git a/presentation/src/main/res/values-ar/strings.xml b/presentation/src/main/res/values-ar/strings.xml index 826a01d62bfe3e9404379c7c4b2abfa10849623b..2eb5225aec3c2cb43b3979889529a990dfa2f441 100644 --- a/presentation/src/main/res/values-ar/strings.xml +++ b/presentation/src/main/res/values-ar/strings.xml @@ -1,5 +1,4 @@ - + --> + محادثة جديدة ألِّف الاختصار معطَّل أُرشفت الإعدادات الإشعارات - البحث في علبة الوارد… + السمة + البحث في علبة الوارد… أكتب اسماً أو رقماً تخطي متابعة @@ -55,11 +56,12 @@ ستظهر المحادثات المؤرشفة الخاصة بك هنا بدء محادثة جديدة ستحب المراسلة ثانية - جعل Message تطبيق الرسائل النصية الافتراضي لديك + جعل QKSMS تطبيق الرسائل النصية الافتراضي لديك تغيير الإذن مطلوب - Message يحتاج إلى إذن لإرسال وعرض الرسائل النصية - Message يحتاج إلى إذن لعرض جهات الاتصال لديك + QKSMS يحتاج إلى إذن لإرسال وعرض الرسائل النصية + QKSMS يحتاج إلى إذن لعرض جهات الاتصال لديك + QKSMS needs permission to display notifications سماح صندوق الوارد المؤرشفة @@ -100,8 +102,9 @@ بطاقة جهة الاتصال مجدولة لـ الوقت المحدّد يجب أن يكون مستقبلاً! + يلزمك فك QKSMS+ لاستخدام التراسل المجدول أضيفت إلى الرسائل المجدولة - كتابة رسالة… + كتابة رسالة… نسخ النص إعادة توجيه حذف @@ -147,33 +150,32 @@ النسخ الاحتياطي والاستعادة النسخ الاحتياطي للرسائل استعادة من النسخة الاحتياطية - آخر نسخ احتياطي - تحميل… + تحميل… أبداً + Backup location + Set folder استعادة اختر نسخة احتياطية - النسخ الاحتياطي قيد التقدم… - الاستعادة قيد التقدُّم… + يرجى إلغاء تأمين QKSMS+ للتمكن من استخدام النسخ الاحتياطي والاستعادة + النسخ الاحتياطي قيد التقدم… + الاستعادة قيد التقدُّم… الاستعادة من النسخ الاحتياطي - هل أنت متأكد من رغبتك استرجاع رسائلك من هذه النسخة الاحتياطية؟ إيقاف الاستعادة الرسائل التي تمت استعادتها ستبقى في جهازك + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details النسخ الاحتياطية لا توجد أي نسخة احتياطية - - لا رسائل - رسالة - رسالتان - %d رسائل - %d رسائل - %d رسائل - النسخ الاحتياطي والاستعادة متاحة الآن فقط للرسائل النصّية. دعم رسائل الوسائط والرسائل المجدولة قادم قريباً! النسخ الاحتياطي الآن - توزيع النسخ الاحتياطي… + توزيع النسخ الاحتياطي… %d/%d رسائل - جارٍ حفظُ النسخة الاحتياطية… - مزامنة الرسائل جارية… + جارٍ حفظُ النسخة الاحتياطية… + مزامنة الرسائل جارية… تم! النسخ الاحتياطي والاستعادة مجدولة @@ -245,9 +247,9 @@ عدد الايام لا نهائيا مسح الرسائل القديمة تلقائيا؟ - If you proceed, %1$d messages will be deleted now + إذا قمت بالمتابعة، سيتم حذف %1$d رسالة الآن - بعد يوم واحد + بعد 1 يوم After 1 day After %d days After %d days @@ -255,21 +257,21 @@ After %d days ارسل الرسائل الطويلة كرسائل الوسائط المتعددة - If your longer text messages are failing to send, or sending in the wrong order, you can send them as MMS messages instead. Additional charges may apply + اذا فشلت رسالتك النصية الطويلة, او ارسلت بلترتيب الخاطئ, يمكنك ارسالها كرسالة MMS بدلا من ذلك, سوف يتم احتساب رسوم اضافية الضغط التلقائي لمرفقات رسائل الوسائط مزامنة الرسائل إعادة مزامنة رسائلك مع قاعدة البيانات الأصلية للرسائل في النظام - حول Message + حول QKSMS النسخة %s تسجيل التصحيح مفعَّل تسجيل التصحيح معطَّل أدخل المدة (ثوان) المحظورات - Drop messages + مسح الرسائل Drop incoming messages from blocked senders instead of hiding them المحادثات المحظورة مدير المحظورات - QKSMS + كيو كي اس ام اس Built-in blocking functionality in QKSMS Block spam messages, numbers & unknown calls with blacklist & Schedule Automatically filter your calls and messages in one convenient place! Community IQ™ allows you to prevent unwanted messages from community known spammers @@ -318,7 +320,7 @@ افتح + التبرع ل %1$s%2$s شكراً لكم على دعم QKSMS! جميع ميزات QKSMS+ متاحة لك الآن - An error has occurred, please try again + حدث خطا, يرجى اعادة المحاولة QKSMS+ مجاني لمستخدمي متجر ف-درويد! لا تتردد في التبرع إن كنت ترغب دعم تطوير هذا التطبيق. التبرع عن طريق بي بال قريباً @@ -374,6 +376,7 @@ تراجع تم النسخ تم حفظ المحادثة + استخدام هذه الميزة يتطلب فتح QKSMS+ لا رسائل جديدة رسالة جديدة @@ -431,11 +434,4 @@ ههههههه هذا مناسب - يجب عليك فتح QKSMS + لاستخدام هذا - المؤلفون - نسخة التطبيق - رسالة - معلومات الرسالة - سياسة الخصوصية - شروط الخدمة diff --git a/presentation/src/main/res/values-bn/e_strings.xml b/presentation/src/main/res/values-bn/e_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..c01beda1b6df128591959b38c07ce6a6fbf3ca3b --- /dev/null +++ b/presentation/src/main/res/values-bn/e_strings.xml @@ -0,0 +1,22 @@ + + + + মেসেজের এসএমএস বার্তাগুলো পাঠানোর এবং দেখার অনুমতি প্রয়োজন + মেসেজের তোমার পরিচিতিগুলি দেখার জন্য অনুমতি প্রয়োজন + মেসেজ সম্পর্কে + মেসেজের অন্তর্ভুক্ত অবরোধী সক্ষমতা(blocking) + \ No newline at end of file diff --git a/presentation/src/main/res/values-bn/strings.xml b/presentation/src/main/res/values-bn/strings.xml index 48224ac152918e2bf21cda1bcdefe49ba8152608..fc072538bdc88eab43cfbc73365cb1e238726467 100644 --- a/presentation/src/main/res/values-bn/strings.xml +++ b/presentation/src/main/res/values-bn/strings.xml @@ -1,5 +1,4 @@ - - Åbn samtale + Ny samtale Skriv Genvej deaktiveret Arkiveret Indstillinger Notifikationer - Søg i Indbakke… + Tema + Søg indbakke… Angiv et navn eller nummer - Overspring + Spring over Fortsæt Tilføj person Opkald @@ -55,11 +56,12 @@ Dine arkiverede samtaler vil fremgå her Start ny samtale Elsk at SMS\'e igen - Gør Message til din standard SMS-app + Gør QKSMS til din standard SMS-app Skift Tilladelse nødvendig - Message behøver tilladelse til at sende og vise SMS\'er - Message behøver tilladelse til at se dine kontakter + QKSMS behøver tilladelse til at sende og vise SMS\'er + QKSMS behøver tilladelse til at se dine kontakter + QKSMS behøver tilladelse til at vise notifikationer Tillad Indbakke Arkiveret @@ -69,6 +71,11 @@ Indstillinger Hjælp og feedback Invitér venner + Oplås fantastiske nye funktioner og støt udvikling + Synes om QKSMS? + Del og bedøm os på Google Play! + OKAY! + AFVIS Slet Sikker på, at du vil slette denne samtale? @@ -91,6 +98,7 @@ Kontaktkort Planlagt til Valgte tidspunkt skal være i fremtiden! + Du skal oplåse QKSMS+ for at benytte planlagt beskedfunktion Føjet til planlagte beskeder Skriv en besked… Kopier tekst @@ -127,6 +135,7 @@ Adresse kopieret Samtaletitel Notifikationer + Tema Arkiv Fjern fra arkiv Blokér @@ -137,23 +146,26 @@ Sikkerhedskopiering og gendannelse Sikkerhedskopierer beskeder Gendanner fra sikkerhedskopi - Seneste sikkerhedskopi Indlæser… Aldrig + Placering af sikkerhedskopi + Indstil mappe Gendanne Vælg en sikkerhedskopi + Oplås QKSMS+ for at benytte sikkerhedskopiering og gendannelse Sikkerhedskopiering i gang… Gendannelse i gang… Genskab fra sikkerhedskopi - Er du sikker på at du vil gendanne dine beskeder fra denne sikkerhedskopi? Stop gendannelsen Beskeder som allerede er genskabt vil forblive på din enhed + Vælg placering af sikkerhedskopi + Vælg en mappe til lagring af sikkerhedskopier + %1$s\n%2$d beskeder + Fejl + Kunne ikke læse sikkerhedskopifil + Sikkerhedskopioplysninger Sikkerhedskopier Ingen sikkerhedskopier fundet - - %d besked - %d beskeder - I øjeblikket understøtter Sikkerhedskopiering og Gendannelse kun SMS. MMS-understøttelse og planlagte sikkerhedskopieringer kommer snart! Sikkerhedskopiér nu Analyserer sikkerhedskopi… @@ -179,6 +191,7 @@ Udseende Generelt QK-svar + Tema Nattilstand Ren sort nattilstand Starttidspunkt @@ -240,7 +253,7 @@ Auto-komprimér MMS-vedhæftninger Beskedsynkronisering Gen-synkroniéer beskeder med den indbyggede Android SMS-database - Om Message + Om QKSMS Version %s Fejlfindingslogning aktiveret Fejlfindingslogning deaktiveret @@ -252,9 +265,9 @@ Blokeringshåndtering QKSMS Indbygget blokeringsfunktionalitet i QKSMS - Block spam messages, numbers & unknown calls with blacklist & Schedule - Filtrér automatisk dine opkald og beskeder på ét praktisk sted! Community IQ ™ giver dig mulighed for at forhindre uønskede beskeder fra spammere kendt af fællesskabet - Filtrér automatisk beskeder fra uopfordrede numre vha. \"Bør jeg besvare\"-app\'en + Blokér spambeskeder, numre & ukendte opkald med sortliste & tidsplan + Filtrér automatisk dine opkald og beskeder på ét praktisk sted! Community IQ™ giver dig mulighed for at forhindre uønskede beskeder fra spammere kendt af fællesskabet + Filtrér automatisk beskeder fra uopfordrede numre vha. \"Should I Answer?\" app\'en Kopiér blokerede numre Fortsæt til %s og kopiér dine blokerede nummer dertil Blokerede numre @@ -291,7 +304,7 @@ Oplås + donér for %1$s %2$s Tak for din støtte til QKSMS! Du har nu adgang til alle QKSMS+-funktioner - An error has occurred, please try again + Der opstod en fejl, prøv igen QKSMS+ er gratis for F-Droid-brugere! Ønsker du at støtte udviklingen, er du velkommen til at donere. Donér via PayPal Kommer snart @@ -323,6 +336,9 @@ Vis flere Vis mindre Åbn samtale + Material + HEX + Anvend Ingen Arkivér @@ -343,6 +359,7 @@ Fortryd Kopieret Arkiveret samtale + Dette kræver oplåsning af QKSMS+ Ny besked %s nye beskeder diff --git a/presentation/src/main/res/values-de/e_strings.xml b/presentation/src/main/res/values-de/e_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..a8f52bcd485218f90ebd567860e1d637ce48e8f5 --- /dev/null +++ b/presentation/src/main/res/values-de/e_strings.xml @@ -0,0 +1,31 @@ + + + + Nachrichten + Nachrichten als Standard-SMS-App festlegen + Nachrichten benötigt die Berechtigung zum Senden und Anzeigen von SMS-Nachrichten + Nachrichten benötigt die Berechtigung zum Zugreifen auf die Kontakte + Über Message + Nachrichten ist eine Abänderung von QKSMS + Information über Nachrichten + - Nachrichten ist eine quelloffene Anwendung, welche die Original-App von Android ersetzt. + Datenschutz-Bestimmungen + Nutzungsbedingungen + Autoren + Es ist unmöglich, eine leere Nummer hinzuzufügen! Bitte versuche es erneut. + Es ist unmöglich, einen leeren Text hinzuzufügen! Bitte versuche es erneut. + \ No newline at end of file diff --git a/presentation/src/main/res/values-de/strings.xml b/presentation/src/main/res/values-de/strings.xml index 7f0d0ae554f9b83dad03f0bf4fc2a400bfb2913b..ac639f37b466b23f640316b8ca71bb562fb6c617 100644 --- a/presentation/src/main/res/values-de/strings.xml +++ b/presentation/src/main/res/values-de/strings.xml @@ -1,5 +1,5 @@ - + --> + Neue Unterhaltung Verfassen Schnellzugriff deaktiviert Archiviert Einstellungen Benachrichtigungen - In Posteingang suchen… + Erscheinungsbild + In Posteingang suchen… Verfassen Überspringen Weiter + Person hinzufügen Anrufen Details In Galerie speichern - Menüleiste öffnen + Teilen + Öffne den Navigation Drawer %d ausgewählt Zurücksetzen Archivieren @@ -42,7 +46,7 @@ Als gelesen markieren Als ungelesen markieren Blockieren - Synchronisiere Nachrichten… + Synchronisiere Nachrichten… Du: %s Entwurf Ergebnisse in Nachrichten @@ -51,12 +55,13 @@ Keine Ergebnisse Archivierte Unterhaltungen werden hier angezeigt Neue Unterhaltung starten - Liebe es, wieder SMS zu schreiben - Nachrichten als Standard-SMS-App festlegen + Liebe es wieder, SMS zu schreiben + QKSMS als Standard-SMS-App festlegen Ändern Berechtigung erforderlich - Nachrichten benötigt die Berechtigung zum Senden und Anzeigen von SMS-Nachrichten - Nachrichten benötigt die Berechtigung zum Zugreifen auf die Kontakte + QKSMS benötigt die Berechtigung zum Senden und Anzeigen von SMS-Nachrichten + QKSMS benötigt die Berechtigung zum Zugreifen auf die Kontakte + QKSMS benötigt die Berechtigung, um Benachrichtigungen anzuzeigen Zulassen Posteingang Archiviert @@ -66,26 +71,36 @@ Einstellungen Hilfe & Feedback Freunde einladen + Schalte erstaunliche Neue Funktionen frei und unterstütze die Entwicklung + Gefällt dir QKSMS? + Teile etwas von deiner Liebe und Bewerte uns auf Google Play! + OKAY! + VERWERFEN Löschen - Bist du sicher, dass du diese Unterhaltung löschen möchtest\? - Bist du sicher, dass du %d Unterhaltungen löschen möchtest\? + Bist du sicher, dass du diese Unterhaltung löschen möchtest? + Bist du sicher, dass du %d Unterhaltungen löschen möchtest? Text kopieren Weiterleiten Löschen + Wählen Sie eine Telefonnummer + %s - Standard + Nur einmal + Immer %d ausgewählt %1$d von %2$d Ergebnissen Als Gruppennachricht senden Empfänger und Antworten werden für jeden sichtbar sein - Das ist der Beginn der Unterhaltung. Sag was Nettes! + Das ist der Beginn der Unterhaltung. Sag\' etwas Nettes! Kontaktkarte Geplant für Gewählte Zeit muss in der Zukunft liegen! + Für diese Funktion muss QKSMS+ freigeschalten werden Zu geplanten Nachrichten hinzugefügt - Schreibe eine Nachricht… + Schreibe eine Nachricht… Text kopieren Weiterleiten Löschen @@ -109,14 +124,18 @@ Plane Nachricht Kontakt anhängen Fehler beim Lesen des Kontaktes + + SIM %1$d (%2$s) ausgewählt %s ausgewählt, SIM-Karte ändern Nachricht senden - Wird gesendet … + Wird gesendet… Zugestellt %s Fehler beim Senden. Tippen, um es erneut zu versuchen Details + Adresse kopiert Unterhaltungstitel Benachrichtigungen + Erscheinungsbild Archivieren Wiederherstellen Blockieren @@ -127,29 +146,32 @@ Sichern und Wiederherstellen Sichere Nachrichten Aus Sicherung wiederherstellen - Letzte Sicherung - Wird geladen … + Lade… Niemals + Sicherungsort + Ordner festlegen Wiederherstellen Sicherung auswählen - Sicherung wird durchgeführt … - Wiederherstellung wird durchgeführt … + Bitte QKSMS+ freischalten, um die Sicherung und Wiederherstellung zu nutzen + Sicherung wird durchgeführt… + Wiederherstellung wird durchgeführt… Aus einer Sicherung wiederherstellen - Sicher, dass die Nachrichten aus dieser Sicherung wiederhergestellt werden sollen? Wiederherstellung abbrechen Nachrichten, die bereits wiederhergestellt wurden, werden auf Ihrem Gerät bleiben + Sicherungsort auswählen + Bitte wählen Sie einen Ordner in dem Sie Ihre Sicherungen speichern möchten + %1$s\n%2$d Nachrichten + Fehler + Sicherungsdatei konnte nicht gelesen werden + Sicherungsdetails Sicherungen Keine Sicherungen gefunden - - %d Nachricht - %d Nachrichten - Derzeit wird nur das Sichern und Wiederherstellen von SMS unterstützt. Die Unterstützung für MMS und geplante Sicherungen folgen demnächst! Jetzt sichern - Analysiere Sicherung … + Analysiere Sicherung… %d/%d Nachrichten - Sicherung wird gespeichert … - Synchronisiere Nachrichten … + Sicherung wird gespeichert… + Synchronisiere Nachrichten… Fertig! Sicherung und Wiederherstellung Geplant @@ -159,7 +181,7 @@ Alles Gute zum Geburtstag! Schau was für ein großartiger Freund ich bin, dass ich an deinen Geburtstag denke Am 23. Dezember senden  - Nachricht planen + Nachricht verschieben Geplante Nachricht Sofort senden @@ -169,10 +191,12 @@ Aussehen Allgemein Schnellantwort + Erscheinungsbild Nachtmodus Rein schwarzer Nachtmodus Anfang Ende + Automatische Kontaktfarben Schriftgröße Systemschriftart verwenden Automatische Emoji @@ -183,6 +207,7 @@ Taste 2 Taste 3 Benachrichtigungsvorschau + Bildschirm aufwecken Vibration Ton Keine @@ -213,10 +238,22 @@ Akzente aus Zeichen in ausgehenden SMS-Nachrichten entfernen Nur Mobilfunknummern Beim Verfassen einer Nachricht nur Mobilfunknummern anzeigen + Alte Nachrichten automatisch löschen + Nachrichten werden nach der angegebenen Anzahl von Tagen gelöscht + Anzahl der Tage + Niemals + Alte Nachrichten automatisch löschen? + Wenn Sie fortfahren, werden jetzt %1$d Nachrichten gelöscht + + Nach 1 Tag + Nach %d Tagen + + Lange Nachrichten als MMS senden + Wenn Ihre längeren Textnachrichten nicht gesendet oder in der falsche Reihenfolge gesendet werden, können Sie sie stattdessen als MMS-Nachrichten senden. Dafür können zusätzliche Gebühren anfallen. MMS-Anhänge automatisch komprimieren Nachrichten synchronisieren Nachrichten mit der Android SMS-Datenbank abgleichen - Über Message + Über QKSMS Version %s Protokollierung zur Fehlerbehebung aktiviert Protokollierung zur Fehlerbehebung deaktiviert @@ -228,6 +265,7 @@ Blockiermanager QKSMS In QKSMS integrierte Blockierfunktion + Spam-Nachrichten und Nummern & unbekannte Anrufe mit Sperrliste & Zeitplan blockieren Filtern Sie automatisch Ihre Anrufe und Nachrichten in einer geeigneten Umgeben! Community IQ™ erlaubt es Ihnen unerwünschte Nachrichten von bekannten Spamnern zu unterbinden Nachrichten von unerwünschten Nummern automatisch mit Hilfe der App \"Should I Answer?\" filtern blockierte Nummer(n) kopieren @@ -253,7 +291,7 @@ Über Version Entwickler - Quellcode + Quelltext Änderungsprotokoll Kontakt Lizenz @@ -266,6 +304,7 @@ Entsperren & Spenden für %1$s %2$s Vielen Dank für die Unterstützung von QKSMS! Du kannst jetzt alle QKSMS+ Funktionen verwenden + Ein Fehler ist aufgetreten, bitte versuchen Sie es erneut QKSMS+ ist für Nutzer von F-Droid kostenfrei! Spende gerne um die Entwicklung zu Unterstützen. Spenden per PayPal Demnächst verfügbar @@ -289,7 +328,7 @@ Eingehende Nachrichten werden mit einer voreingestellten Antwort beantwortet Mehr QKSMS wird aktiv weiterentwickelt und Dein Erwerb wird alle zukünftigen Funktionen enthalten! - Wird geladen … + Lädt… Weitere Unterhaltungen anzeigen Als gelesen markieren Anrufen @@ -297,6 +336,9 @@ Mehr anzeigen Weniger anzeigen Unterhaltung öffnen + Material + HEX + Übernehmen Nichts Archiv @@ -317,6 +359,7 @@ Rückgängig Kopiert Archivierte Unterhaltung + Für diese Funktion muss QKSMS+ freigeschalten werden Neue Nachricht %s neue Nachrichten @@ -342,9 +385,9 @@ Keine Verzögerung - Kurz - Mittel - Lang + 3 Sekunden + 5 Sekunden + 10 Sekunden Automatisch @@ -370,52 +413,4 @@ LOL Das ist OK - Autoren - Nutzungsbedingungen - Datenschutz-Bestimmungen - App-Version - Information über Nachrichten - Nachrichten - Für diese Funktion ist QKSMS+ erforderlich - Material - Ein Fehler ist aufgetreten, bitte versuche es erneut - - Nachrichten ist eine quelloffene Anwendung, welche die Original-App von Android ersetzt. - Nachrichten ist eine Abänderung von QKSMS - Spam-Nachrichten, Nummern und unbekannte Anrufer mit Sperrliste und Zeitplan blockieren - Wenn längere Nachrichten nicht gesendet werden, oder in einer falschen Ordnung gesendet werden, kannst du sie auch als MMS-Nachricht senden. Zusatzkosten können anfallen. - Lange Nachrichten als MMS senden - - Nach 1 Tag - Nach %d Tagen - - Wenn du bestätigst, werden %1$d Nachrichten nun gelöscht - Alte Nachrichten automatisch löschen\? - Niemals - Anzahl der Tage - Nachrichten werden nach einer bestimmten Anzahl von Tagen gelöscht - Alte Nachrichten automatisch löschen - Bildschirm aufwecken - Automatische Kontaktfarben - Thema - Bitte entsperre QKSMS+, um die Sicherungs- und Wiederherstellungsfunktion nutzen zu können - Thema - Adresse kopiert - SIM %1$d (%2$s) ausgewählt - Du musst QKSMS+ entsperren, um geplante Nachrichten nutzen zu können - Immer - Nur einmal - %s ∙Standard - Eine Telefonnummer auswählen - Teilen - Person hinzufügen - Thema - Es ist unmöglich, einen leeren Text hinzuzufügen! Bitte versuche es erneut. - Es ist unmöglich, eine leere Nummer hinzuzufügen! Bitte versuche es erneut. - VERWERFEN - OK! - Teile deine Vorliebe und bewerte uns auf Google Play! - Gefällt dir Nachrichten\? - Entsperre tolle neue Funktionen und unterstütze die Weiterentwicklung - Anwenden - HEX diff --git a/presentation/src/main/res/values-el/strings.xml b/presentation/src/main/res/values-el/strings.xml index 87346d034020cb0e7d12c217bfc939e22f14b001..d4a9e7f73a26c1b77e3e8e54afce1d738347f32d 100644 --- a/presentation/src/main/res/values-el/strings.xml +++ b/presentation/src/main/res/values-el/strings.xml @@ -1,5 +1,4 @@ - + SIM %1$d (%2$s) selected Επελέγη το %s, αλλάξτε την κάρτα SIM Αποστολή μηνύματος Αποστολή… Παραδόθηκε: %s Αποτυχία αποστολής. Πατήστε για νέα προσπάθεια Λεπτομέρειες + Η διεύθυνση αντεγράφη Τίτλος συζήτησης Ειδοποιήσεις + Θέμα εμφάνισης Αρχειοθέτηση Αναίρεση αρχειοθέτησης Φραγή @@ -130,24 +146,26 @@ Αντίγραφα ασφαλείας και επαναφορά Δημιουργία αντιγράφου ασφαλείας μηνυμάτων Επαναφορά αντιγράφου ασφαλείας μηνυμάτων - Τελευταίο αντίγραφο ασφαλείας Φόρτωση… Ποτέ + Backup location + Set folder Επαναφορά Επιλέξτε ένα αντίγραφο ασφαλείας Παρακαλώ ξεκλειδώστε το QKSMS+ για τη δημιουργία και επαναφορά αντιγράφων ασφαλείας Δημιουργία αντιγράφου ασφαλείας… Επαναφορά αντιγράφου ασφαλείας… Επαναφορά αντιγράφου ασφαλείας - Σίγουρα επιθυμείτε να επαναφέρετε τα μηνύματα σας από αυτό το αντίγραφο ασφαλείας; Διακοπή επαναφοράς Τα μηνύματα που έχουν ήδη ανακτηθεί θα παραμείνουν στη συσκευή σας + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details Αντίγραφα ασφαλείας Δεν βρέθηκαν αντίγραφα ασφαλείας - - %d message - %d μηνύματα - Προς το παρόν, μπορούν να δημιουργηθούν αντίγραφα ασφαλείας μόνο για SMS. Η υποστήριξη MMS και ο προγραμματισμός αντιγράφων ασφαλείας θα προστεθούν σύντομα! Δημιουργία αντιγράφου τώρα Ανάγνωση αντιγράφου ασφαλείας… @@ -173,10 +191,12 @@ Εμφάνιση Γενικά Γρήγορη απάντηση + Θέμα εμφάνισης Νυχτερινή λειτουργία Νυχτερινή λειτουργία καθαρού μαύρου Ώρα έναρξης Ώρα λήξης + Αυτόματος χρωματισμός επαφών Μέγεθος γραμματοσειράς Χρήση γραμματοσειράς συστήματος Αυτόματα emoji @@ -187,6 +207,7 @@ Κουμπί 2 Κουμπί 3 Προεπισκοπήσεις ειδοποιήσεων + Ενεργοποίηση οθόνης Δόνηση Ήχος Κανένα @@ -211,16 +232,28 @@ Επιβεβαιώσεις παράδοσης Confirm that messages were sent successfully - Signature + Υπογραφή Add a signature to the end of your messages Strip accents Remove accents from characters in outgoing SMS messages Mobile numbers only When composing a message, only show mobile numbers + Delete old messages automatically + Messages will be deleted after the specified number of days + Number of days + Never + Delete old messages automatically? + If you proceed, %1$d messages will be deleted now + + After 1 day + After %d days + + Send long messages as MMS + If your longer text messages are failing to send, or sending in the wrong order, you can send them as MMS messages instead. Additional charges may apply Auto-compress MMS attachments - Sync messages - Re-sync your messages with the native Android SMS database - About Message + Συγχρονισμός μηνυμάτων + Επανασυγχρονισμός μηνυμάτων με τη βάση δεδομένων SMS του Android + Σχετικά με το QKSMS Έκδοση %s Η καταγραφή σφαλμάτων ενεργοποιήθηκε Η καταγραφή σφαλμάτων απενεργοποιήθηκε @@ -232,11 +265,12 @@ Διαχειριστής φραγής QKSMS Ενσωματωμένη λειτουργία φραγής του QKSMS + Block spam messages, numbers & unknown calls with blacklist & Schedule Automatically filter your calls and messages in one convenient place! Community IQ™ allows you to prevent unwanted messages from community known spammers Automatically filter messages from unsolicited numbers by using the \"Should I Answer\" app - Copy blocked numbers + Αντιγραφή αριθμών με φραγή Continue to %s and copy over your existing blocked numbers - Blocked numbers + Αριθμοί με φραγή Your blocked numbers will appear here Block a new number Block texts from @@ -270,6 +304,7 @@ Unlock + donate for %1$s %2$s Thank you for supporting QKSMS! You now have access to all QKSMS+ features + An error has occurred, please try again QKSMS+ is free for F-Droid users! If you\'d like to support development, a donation would be highly appreciated. Δωρεά μέσω PayPal Έρχεται σύντομα @@ -295,12 +330,15 @@ QKSMS is under active development, and your purchase will include all future QKSMS+ features! Loading… View more conversations - Mark as read + Mark read Call Delete Show more Show less Open conversation + Material + HEX + Apply None Archive @@ -321,6 +359,7 @@ Undo Copied Archived conversation + You must unlock QKSMS+ to use this New message %s new messages @@ -346,9 +385,9 @@ No delay - Short - Medium - Long + 3 seconds + 5 seconds + 10 seconds Automatic diff --git a/presentation/src/main/res/values-es/e_strings.xml b/presentation/src/main/res/values-es/e_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..d2c1e20fbe590e5acb414774043ee7a91a3944db --- /dev/null +++ b/presentation/src/main/res/values-es/e_strings.xml @@ -0,0 +1,23 @@ + + + + Mensajes + Haga de Message su aplicación SMS por defecto + Message necesita permiso para enviar y ver mensajes SMS + Message necesita permiso para ver sus contactos + Acerca de Message + \ No newline at end of file diff --git a/presentation/src/main/res/values-es/strings.xml b/presentation/src/main/res/values-es/strings.xml index 4c53c4eef7067f8efbf44a49d7b4890d3e13356c..f8bff52f1f35a42d588adee0734133e0b3ba501b 100644 --- a/presentation/src/main/res/values-es/strings.xml +++ b/presentation/src/main/res/values-es/strings.xml @@ -16,14 +16,16 @@ ~ ~ You should have received a copy of the GNU General Public License ~ along with QKSMS. If not, see . - --> + --> + Nueva conversación Redactar Acceso directo deshabilitado Archivados Configuración Notificaciones - Buscar mensaje… + Tema + Buscar mensaje… Escriba un nombre o número Omitir Continuar @@ -54,11 +56,12 @@ Sus conversaciones archivadas aparecerán aquí Iniciar una nueva conversación Me encanta enviar mensajes de texto otra vez - Haga de Message su aplicación SMS por defecto + Haga de QKSMS su aplicación SMS por defecto Cambios Se requiere permiso - Message necesita permiso para enviar y ver mensajes SMS - Message necesita permiso para ver sus contactos + QKSMS necesita permiso para enviar y ver mensajes SMS + QKSMS necesita permiso para ver sus contactos + QKSMS needs permission to display notifications Permitir Recibidos Archivar @@ -68,6 +71,11 @@ Ajustes Ayuda & comentarios Invitar amigos + Desbloquea nuevas e impresionantes características y apoya el desarrollo + ¿Te diviertes con QKSMS? + Comparte un poco de amor y puntúanos en Google Play! + DE ACUERDO + DESESTIMAR Eliminar ¿Está seguro de que desea eliminar la conversación? @@ -90,8 +98,9 @@ Tarjeta de contacto Programado para El tiempo seleccionado debe de ser en el futuro! + Tienes que desbloquear QKSMS+ para usar mensajes programados Añadido a los mensajes programados - Escribir mensaje… + Escribir mensaje… Copiar texto Reenviar Eliminar @@ -119,13 +128,14 @@ SIM %1$d (%2$s) seleccionada %s seleccionado, cambia la tarjeta SIM Enviar mensaje - Enviando… + Enviando… Entregado %s No se pudo enviar. Pulse para volver a intentarlo Detalles Dirección copiada Título de la conversación Notificaciones + Tema Archivar Desarchivar Bloquear @@ -136,29 +146,32 @@ Copia de seguridad y restauración Respaldando mensajes Restaurar desde copia de seguridad - Última copia de seguridad - Cargando… + Cargando… Nunca + Backup location + Set folder Restaurar Seleccione una copia de seguridad - Copia de seguridad en progreso… - Restauración en progreso… + Por favor desbloquee QKSMS+ para usar copia de seguridad y restauración + Copia de seguridad en progreso… + Restauración en progreso… Restaurar desde copia de seguridad - ¿Está seguro de que desea restaurar sus mensajes desde esta copia de seguridad? Detener restauración Los mensajes que ya han sido restaurados permanecerán en su dispositivo + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details Copias de seguridad No se encontraron copias de seguridad - - %dNuevo mensaje - %dMensajes nuevos - Actualmente, sólo los SMS son soportados por la copia de seguridad y restauración. ¡El soporte para MMS y las copias de seguridad programadas se realizarán pronto! Copiar ahora - Analizando copia de seguridad… + Analizando copia de seguridad… %d/%d mensajes - Guardando copia de seguridad… - Sincronizando mensajes… + Guardando copia de seguridad… + Sincronizando mensajes… ¡Terminado! Copiar y restaurar Programado @@ -178,6 +191,7 @@ Apariencia General Responder vía QKSMS + Tema Modo nocturno Modo noche negro puro Hora de inicio @@ -224,22 +238,22 @@ Quitar acentos de caracteres en los mensajes SMS salientes Sólo números móviles Al componer un mensaje, sólo mostrar números móviles - Delete old messages automatically - Messages will be deleted after the specified number of days - Number of days - Never - Delete old messages automatically? - If you proceed, %1$d messages will be deleted now + Eliminar mensajes antiguos automáticamente + Los mensajes se eliminarán después del número especificado de días + Número de días + Nunca + ¿Eliminar mensajes antiguos automáticamente? + Si sigues, se eliminarán %1$d mensajes ahora - After 1 day - After %d days + Después de 1 día + Después de %d días Enviar mensajes largos como MMS Si sus mensajes de texto largos no se están enviando o enviando en el orden incorrecto, puede enviarlos como mensajes MMS en su lugar. Se pueden aplicar cargos adicionales Autocomprimir archivos adjuntos MMS Sincronizar mensajes Vuelve a sincronizar tus mensajes con la base de datos nativa de Android SMS - Acerca de Message + Acerca de QKSMS Versión %s Registro de depuración activado Registro de depuración desactivado @@ -249,7 +263,7 @@ Eliminar mensajes entrantes de los remitentes bloqueados en lugar de ocultarlos Conversaciones bloqueadas Gestor de bloqueo - Message + QKSMS Función de bloqueo integrado en QKSMS Bloquee mensajes de spam, números y llamadas desconocidas con lista negra y programación ¡Filtrre automáticamente sus llamadas y mensajes en un lugar conveniente! La comunidad IQ™ te permite prevenir mensajes no deseados de spammers conocidos por la comunidad @@ -290,7 +304,7 @@ Desbloquear + donación %1$s %2$s Gracias por apoyar a QKSMS! Ahora tienes acceso a todas las funciones de QKSMS + - An error has occurred, please try again + Se ha producido un error. Por favor, inténtalo de nuevo. QKSMS+ es gratis para los usuarios de F-Droid! Si desea apoyar el desarrollo, no dude en hacer una donación. Donar con PayPal Próximamente @@ -314,7 +328,7 @@ Responder automáticamente a mensajes entrantes con una respuesta preestablecida Más QKSMS está bajo desarollo activo, y sus compras incluirán todas las características futuras de QKSMS+! - Cargando… + Cargando… Ver más conversaciones Marcar como leído Llamar @@ -322,6 +336,9 @@ Mostrar más Mostrar menos Abrir conversación + Material + HEXAGONAL + Aplicar Ninguno Archivar @@ -342,6 +359,7 @@ Deshacer Copiado Conversación archivada + Debe desbloquear QKSMS+ para utilizarlo Nuevo mensaje nuevos mensajes de %s @@ -395,5 +413,4 @@ JAJAJA Está bien - Mensajes diff --git a/presentation/src/main/res/values-eu/e_strings.xml b/presentation/src/main/res/values-eu/e_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..83abf2871d7c6b651f63cc29bfd170fa694aaccb --- /dev/null +++ b/presentation/src/main/res/values-eu/e_strings.xml @@ -0,0 +1,27 @@ + + + + Mezuak + Egin Mezuak zure SMS aplikazio lehenetsia + Mezuak aplikazioak SMSak bidali eta ikusteko baimena behar du + Mezuak aplikazioak zure kontaktuak ikusteko baimena behar du + Mezuak aplikazioari buruzko informazioa + Aplikazioaren bertsioa + Pribatutasun politika + Erabilera baldintzak + Egileak + \ No newline at end of file diff --git a/presentation/src/main/res/values-eu/strings.xml b/presentation/src/main/res/values-eu/strings.xml deleted file mode 100644 index 581941d87cbed8efaf4208bef4b274cef1f9018f..0000000000000000000000000000000000000000 --- a/presentation/src/main/res/values-eu/strings.xml +++ /dev/null @@ -1,266 +0,0 @@ - - - Zuk: %s - Mezuak sinkronizatzen… - Blokeatu - Markatu irakurri gabeko gisa - Jo irakurritzat - Kendu aingura - Ainguratu goialdean - Gehitu kontaktuetara - Ezabatu - Desartxibatu - Artxibatu - Garbitu - %d hautatuta - Gorde galerian - Xehetasunak - Deitu - Jarraitu - Saltatu - Idatzi izena edo zenbakia - Bilatu mezua… - Jakinarazpenak - Ezarpenak - Artxibatuta - Lasterbidea desgaituta - Idatzi - Elkarrizketa berria - Hasi elkarrizketa berria - Artxibatutako elkarrizketak hemen agertuko dira - Emaitzarik ez - Zure elkarrizketak hemen agertuko dira - %d mezu - Emaitzak mezuetan - Zirriborroa: %s - Artxibatutakoak - Sarrerako ontzia - Baimendu - Aldatu - Oso gustuko dut berriro testu-mezuak bidaltzea - Ireki nabigazio-panel lerrakorra - Baimena behar da - Mezuen babeskopia egitea - Babeskopia eta leheneratzea - Galerian gorde da - Ezin izan da multimedia kargatu - Ezabatu elkarrizketa - Desblokeatu - Artxibatu - Jakinarazpenak - Elkarrizketaren izenburua - Bidalketak huts egin du. Ukitu berriro saiatzeko - Entregatuta %s - Bidaltzen… - Bidali mezua - %s hautatuta, aldatu SIM txartela - Errorea kontaktua irakurtzean - Erantsi kontaktua - Programatu mezua - Atera argazkia - Erantsi argazkia - Gehitu eranskina - Errore-kodea: %d - Entregatuta: %s - Jasota: %s - Bidalita: %s - Tamaina: %s - Lehentasuna: %s - Gaia: %s - Hartzailea: %s - Igorlea: %s - Idatzi: %s - Mezuaren xehetasunak - Garbitu - Hurrengoa - Ezabatu - Birbidali - Kopiatu testua - Idatzi mezua… - Programatutako mezuetara gehituta - Hautatutako denborak etorkizunean izan behar du! - Noizko programatuta: - Kontaktu-txartela - Elkarrizketaren hasiera da. Esan zerbait atsegina! - Hartzaileak eta erantzunak edonork ikusi ahal izango ditu - Bidali talde-mezu gisa - %d hautatuta - - Ziur zaude elkarrizketa hau ezabatu nahi duzula\? - Ziur zaude %d elkarrizketa ezabatu nahi dituzula\? - - Ezabatu - Gonbidatu lagunak - Blokeatzea - Programatutakoak - Blokeatu - Desartxibatu - Xehetasunak - Aurrekoa - %2$d emaitzetatik %1$d - Laguntza eta iritziak - Ezarpenak - Gehiago - Babeskopiatik leheneratzea - Ez da babeskopiarik aurkitu - Babeskopiak - Gelditu leheneratzea - Ziur zaude mezuak babeskopia honetatik leheneratu nahi dituzula\? - Leheneratu babeskopiatik - Leheneratzea abian… - Babeskopia abian… - Hautatu babeskopia - Leheneratu - Kargatzen… - Azkeneko babeskopia - Jada berrezarri diren mezuak zure gailuan geratuko dira - Inoiz ez - Oraingoz Babeskopia eta leheneratzea aukerak SMSak soilik onartzen ditu. MMSentzako euskarria eta programatutako babeskopiak laster gehituko ditugu! - Amaituta! - Mezuak sinkronizatzen… - Babeskopia gordetzen… - Babeskopia analizatzen… - Egin babeskopia orain - 3 botoia - 2 botoia - 1 botoia - Gau modu beltz hutsa - Gau modua - QK erantzuna - Zorionak! Ikusi zein lagun ona naizen, zure urtebetetze eguna gogoratzen - - Mezu %d - %d mezu - - Bat ere ez - Soinua - Bibrazioa - Jakinarazpenen aurrebista - Ekintzak - Ukitu pertsonalizatzeko - Jakinarazpenak - Emoji automatikoak - Erabili sistemaren letra-tipoa - Letra-tamaina - Amaiera-ordua - Hasiera-ordua - Orokorra - Itxura - Programatutako mezua - Programatu mezua - Abenduaren 23an bidali  - Abenduaren 23an da - Kaixo! Noiz da zure urtebetetzea\? - Bidali mezua automatikoki, nahiko zenukeen momentu zehatzean - Programatuta - Babeskopia eta leheneratzea - QK erantzuna - Gehitu sinadura mezuen amaieran - Sinadura - Konfirmatu mezuak ondo bidaltzen direnean - Entrega-baieztapenak - ALDATU - Atzerapena bidaltzean - Ukitu baztertzeko - Arazketa erregistroak desgaituta - Arazketa erregistroak gaituta - %s bertsioa - Berriro sinkronizatu zure mezuak Android SMSren berezko datu basearekin - Kendu azentuak bidalitako SMS mezuetako karaktereetatik - Kendu azentuak - Aplikazioaren bertsioa - Copyright - Lizentzia - Iturburu-kodea - Bertsioa - Honi buruz - Desblokeatu - Blokeatu - Blokeatutako mezuak hemen agertuko dira - Blokeatutako mezuak - Blokeatu - Telefono zenbakia - Blokeatu honen mezuak: - Blokeatu zenbaki berria - Blokeatu dituzun zenbakiak hemen agertuko dira - Blokeatutako zenbakiak - Kopiatu blokeatutako zenbakiak - QKSMS - Blokeatze-kudeatzailea - Blokeatutako elkarrizketak - Jaregin mezuak - Blokeatzea - Sartu iraupena (segundoak) - Sinkronizatu mezuak - Konprimitu MMS eranskinak automatikoki - Mezu bat idaztean, mugikor zenbakiak soilik erakutsi - Mugikor zenbakiak soilik - Pribatutasun politika - Premium itxurak - Laster erabilgarri - Egin dohaintza PayPal bidez - QKSMS+ dohainik da F-Droid erabiltzaileentzat! Garapenarekin lagundu nahi izanez gero, dohaintzak eskertzekoak dira. - Erabilera baldintzak - Mezuak aplikazioari buruzko informazioa - Pasa hatza ezkerrerantz - Pasa hatza eskuinerantz - Konfiguratu hatz-pasatze ekintzak elkarrizketetarako - Hatz-pasatze ekintzak - Ukitu laster-leihotik kanpo hura ixteko - Mezu berrientzako laster-leihoa - Mezuak aplikazioak zure kontaktuak ikusteko baimena behar du - Mezuak aplikazioak SMSak bidali eta ikusteko baimena behar du - Egin Mezuak zure SMS aplikazio lehenetsia - Mezuak - %d/%d mezu - Programatutako mezuak - Egileak - Ezin izan zaio %s(r)i mezua bidali - Ez da mezua bidali - - Mezu berria - %s mezu berri - - Elkarrizketa artxibatu da - Kopiatuta - Desegin - Ezarri - Gehiago - Gelditu - Gorde - Ezabatu - Utzi - Jarraitu - Bai - Ireki elkarrizketa - Gutxiago erakutsi - Gehiago erakutsi - Ezabatu - Deitu - Jo irakurritzat - Ikusi elkarrizketa gehiago - Kargatzen… - Gehiago - Automatikoki erantzun sarrerako mezuei lehenetsitako erantzun batekin - Automatikoki erantzun - Automatikoki birbidali bidaltzaile batzuen mezuak - Birbidaltze automatikoa - Blokeatu gako-hitzak edo patroiak dituzten mezuak - Blokeatze aurreratua - Gaitu gau-modua eguneko orduaren arabera - Gau-modu automatikoa - Itxaron segundo batzuk mezua bidali aurretik - Atzerapendun bidalketa - Programatu mezuak automatikoki ordu eta egun jakin batean bidaltzeko - Zure mezuen babeskopia automatikoa egiten du. Inoiz ez kezkatu historia galtzeaz, telefonoa aldatu edo galtzen baduzu - Mezuen babeskopia - Sortu auto-emoji lasterbide pertsonalizatuak - Pertsonalizatutako auto-emojiak - Eskerrik asko QKSMS laguntzeagatik! - Gose den garatzaile bati lagundu diezaiokezu %s emanez - Babestu garapena, guztia desblokeatu - Eskatu gabeko zenbakietako mezuak automatikoki iragazi \"Erantzun beharko nuke\?\" aplikazioa erabiliz - Iragazi automatikoki deiak eta mezuak leku egoki batean! Community IQ™ aplikazioari esker, komunitatean ezagunak diren spammer-en mezu ez-desiratuak prebeni ditzakezu - QKSMSn integratutako blokeatze erabilgarritasuna - Ezabatu blokeatutako bidaltzaileen mezuak, hauek ezkutatu beharrean - \ No newline at end of file diff --git a/presentation/src/main/res/values-fa/strings.xml b/presentation/src/main/res/values-fa/strings.xml index 439fd0e3381a47e05a33f1d0cd39a873ea49c94a..ca895955e328048fe81865d28afe1c0672de89cb 100644 --- a/presentation/src/main/res/values-fa/strings.xml +++ b/presentation/src/main/res/values-fa/strings.xml @@ -1,5 +1,4 @@ - + SIM %1$d (%2$s) valittu + %s valittu, vaihda SIM-korttia Lähetä viesti Lähetetään… Toimitettu: %s Lähettäminen epäonnistui. Yritä uudelleen napauttamalla Lisätiedot + Osoite kopioitu Keskustelun otsikko Ilmoitukset + Teema Arkistoi Poista arkistosta Estä @@ -134,25 +146,27 @@ Varmuuskopioi ja palauta Viestejä varmuuskopioidaan Viestejä palautetaan - Viimeisin varmuuskopio Ladataan… Ei koskaan + Backup location + Set folder Palauta Valitse varmuuskopio Ole hyvä ja avaa QKSMS+ käyttääksesi varmuuskopiointia ja palautusta Varmuuskopiointi käynnissä… Palautus käynnissä… - Palauta varmuuskopio - Oletko varma, että haluat palauttaa viestisi tästä varmuuskopiosta? + Palauta varmuuskopiosta Pysäytä palautus - Viestit, jotka on jo palautettu, pysyvät laitteessasi + Aiemmin palautetut viestit pysyvät laitteellasi + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details Varmuuskopiot Varmuuskopioita ei löytynyt - - %d viesti - %d viestiä - - Tällä hetkellä vain SMS-viestejä voidaan varmuuskopioita ja palauttaa. MMS-viestien tuki ja ajoitetut varmuuskopiot saapuvat pian! + Vain tekstiviestejä voidaan varmuuskopioita ja palauttaa tällä hetkellä. Tuki multimediaviesteille ja varmuuskopiointien ajastus tulevat pian! Varmuuskopioi nyt Varmuuskopiota jäsennetään… %d/%d viestiä @@ -162,7 +176,7 @@ Varmuuskopiointi ja palautus Ajoitettu Lähetä viesti automaattisesti haluamallasi ajankohdalla - Hey! When was your birthday again? + Hei! Milloin syntymäpäiväsi olikaan? Se on joulukuun 23. päivänä Hyvää syntymäpäivää! Katso miten hyvä ystävä olen, muistan syntymäpäiväsi @@ -174,33 +188,36 @@ Kopioi teksti Poista - Ulkoasu + Ulkonäkö Yleiset - QK Vastaus + QK-vastaus + Teema Yötila Musta yötilä Aloitusaika Lopetusaika + Automaattiset yhteystietojen värit Fonttikoko Käytä järjestelmäfonttia Automaattinen emoji Ilmoitukset Muokkaa napauttamalla Toiminnot - Nappi 1 - Nappi 2 - Nappi 3 - Esikatselut ilmoituksessa + Painike 1 + Painike 2 + Painike 3 + Ilmoituksien esikatselut + Herätä näyttö Värinä Ääni Ei mitään - QK Vastaus + QK-vastaus Ponnahdusikkuna uusille viesteille Sulje napauttamalla - Tap outside of the popup to close it + Sulje ponnahdusikkuna napauttamalla sen ulkopuolelle Lykätty lähetys Pyyhkäisytoiminnot - Configure swipe actions for conversations + Muokkaa keskustelujen pyyhkäisytoimintoja Pyyhkäisy oikealle Pyyhkäisy vasemmalle MUUTA @@ -216,30 +233,43 @@ Välitystiedot Vahvista, että viestit lähetettiin onnistuneesti Allekirjoitus - Add a signature to the end of your messages + Lisää allekirjoitus viestiesi loppuun Käytä yksinkertaisia merkkejä - Käytä yksinkertaisia merkkejä lähtevissä SMS-viesteissä + Käytä yksinkertaisia merkkejä lähetettävissä tekstiviesteissä Vain matkapuhelinnumerot - When composing a message, only show mobile numbers - Pakkaa MMS-liitteet automaattisesti + Ehdota vain matkapuhelinnumeroita viestejä kirjoittaessasi + Delete old messages automatically + Messages will be deleted after the specified number of days + Number of days + Never + Delete old messages automatically? + If you proceed, %1$d messages will be deleted now + + After 1 day + After %d days + + Lähetä pitkät viestit multimediaviesteinä + Jos pidempien viestiesi lähetys epäonnistuu, tai viestit lähtevät väärässä järjestyksessä, voit lähettää ne multimediaviesteinä. Operaattori saattaa veloittaa tästä lisämaksuja. + Pakkaa multimediaviestien liitteet automaattisesti Synkronoi viestit - Re-sync your messages with the native Android SMS database - Tietoja Message:tä + Synkronoi viestisi uudelleen Androidin oman SMS-tietokannan kanssa + Tietoja QKSMS:tä Versio %s - Debug logging enabled - Debug logging disabled + Virheenkorjauslokien kirjaaminen käytössä + Virheenkorjauslokien kirjaaminen pois käytöstä Syötä kesto (sekuntia) Esto - Drop messages - Drop incoming messages from blocked senders instead of hiding them + Pudota viestit + Pudottaa estettyjen yhteystietojen lähettämät viestit, niiden piilottamisen sijasta Estetyt keskustelut Estojen hallinta QKSMS - Built-in blocking functionality in QKSMS - Automatically filter your calls and messages in one convenient place! Community IQ™ allows you to prevent unwanted messages from community known spammers - Automatically filter messages from unsolicited numbers by using the \"Should I Answer\" app + QKSMS:ään sisäänrakennettu esto-toiminto + Block spam messages, numbers & unknown calls with blacklist & Schedule + Suodata puhelusi ja soittosi automaattisesti, yhdessä kätevässä paikassa! Community IQ™ antaa sinun estää haluamattomia viestejä, yhteisölle tutuilta roskapostin lähettäjiltä + Suodata haluamattomien numeroin lähettämät viestit automaattisesti, \"Should I Answer\" -sovellusta käyttämällä Kopioi estetyt numerot - Continue to %s and copy over your existing blocked numbers + Jatka, ja kopioi jo estämäsi numerot, sovellukseen %s Estetyt numerot Estämäsi numerot näkyvät tässä Estä uusi numero @@ -251,12 +281,12 @@ Estä Salli - Continue to %s and block this number - Continue to %s and block these numbers + Jatka sovellukseen %s, ja estä tämä numero + Jatka sovellukseen %s, ja estä nämä numerot - Continue to %s and allow this number - Continue to %s and allow these numbers + Jatka sovellukseen %s, ja salli tämä numero + Jatka sovellukseen %s, ja salli nämä numerot Tietoja Versio @@ -265,38 +295,39 @@ Muutosloki Yhteystiedot Lisenssi - Tekijänoikeus - Tue kehitystä, avaa kaikki - You can save a starving developer for just %s + Tekijänoikeudet + Tue kehitystä, avaa kaiken + Voit pelastaa nälkää näkevän kehittäjän antamalla %s - Lifetime upgrade for %1$s %2$s + Elinikäinen päivitys hintaan %1$s %2$s - Unlock + donate for %1$s %2$s - Kiitos kun tuit QKSMS:ää! - You now have access to all QKSMS+ features - QKSMS+ is free for F-Droid users! If you\'d like to support development, a donation would be highly appreciated. + Ominaisuuksien avaus + lahjoitus hintaan %1$s %2$s + Kiitos, kun tuit QKSMS:ää! + Olet nyt oikeutettu käyttämään kaikkia QKSMS+ -ominaisuuksia + An error has occurred, please try again + QKSMS+ on ilmainen F-Droidin käyttäjille! Jos haluaisit tukea kehitystyötä tulevaisuudessa, arvostaisimme lahjoitustasi todella paljon. Lahjoita PayPalilla Tulossa pian Premium-teemat - Unlock beautiful theme colors not available on the Material Design palette - Custom auto-emoji - Create custom auto-emoji shortcuts + Avaa upeat teemavärit, joita ei ole saatavilla Material Design -väripaletissa + Mukautettu auto-emoji + Luo mukautettuja auto-emoji -pikakuvakkeita Viestien varmuuskopiointi - Automatically back up your messages. Never again worry about losing your history if you change phones or your phone gets lost + Varmuuskopioi viestisi automaattisesti. Sinun ei enää ikinä tarvitse huolehtia historiasi katoamisesta, jos vaihdat tai hukkaat puhelimesi Ajoitetut viestit Ajoita viestit lähtemään automaattisesti tiettyinä aikoina ja päivinä Lykätty lähetys Odota muutama sekunti ennen viestin lähettämistä Automaattinen yötila - Enable night mode based on the time of day + Ota yötila käyttöön päivänajan perusteella Edistynyt estäminen - Block messages that contain keywords or match patterns + Estä avainsanoja tai vastaavuuksia sisältävät viestit Automaattinen välitys - Välitä tiettyjen lähettäjien viestit automaattisesti + Edelleenlähetä tiettyjen lähettäjien viestit automaattisesti Automaattinen vastaus - Automatically respond to incoming messages with a preset response + Vastaa saapuviin viesteihin automaattisesti, etukäteen luoduilla vastauksilla Lisää - QKSMS is under active development, and your purchase will include all future QKSMS+ features! + QKSMS:ää kehitetään aktiivisesti, ja ostoksesi sisältää kaikki tulevat QKSMS+ -ominaisuudet! Ladataan… Näytä lisää keskusteluja Merkitse luetuksi @@ -305,6 +336,9 @@ Näytä lisää Näytä vähemmän Avaa keskustelu + Material + HEX + Käytä Ei mitään Arkistoi @@ -322,9 +356,10 @@ Lopeta Lisää Aseta - Peru + Kumoa Kopioitu Arkistoidut keskustelut + Sinun pitää avata QKSMS+ käyttääksesi tätä Uusi viesti %s uutta viestiä @@ -350,9 +385,9 @@ Ei viivettä - Lyhyt - Keskikokoinen - Pitkä + 3 sekuntia + 5 sekuntia + 10 sekuntia Automaattinen @@ -365,7 +400,7 @@ Ei pakkausta - Kyllä + Okei Anna minulle hetki Olen matkalla Kiitos diff --git a/presentation/src/main/res/values-fr/e_strings.xml b/presentation/src/main/res/values-fr/e_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..4fb36d6cfcbbbe16ae6bbf92c0c10c90e562767d --- /dev/null +++ b/presentation/src/main/res/values-fr/e_strings.xml @@ -0,0 +1,31 @@ + + + + Faire de Message votre application SMS par défaut + Message a besoin de l\'autorisation d’envoyer et de consulter des messages SMS + Message a besoin de l\'autorisation d\'accéder aux contacts + À propos de Message + Message est dérivée de QKSMS + Informations sur Message + Version de l\'application + - Message est une application de messagerie open source remplaçant l\'application d\'origine sur Android. + Politique de confidentialité + Conditions d\'utilisation + Auteurs + Impossible d\'ajouter un numéro vide ! Merci de réessayer + Impossible d\'ajouter du texte vide ! Merci de réessayer + \ No newline at end of file diff --git a/presentation/src/main/res/values-fr/strings.xml b/presentation/src/main/res/values-fr/strings.xml index 068a9e644e578b35564316aeb5e02efbcdd3bd80..fb36de833f73a1620759af32b32b12530249be4c 100644 --- a/presentation/src/main/res/values-fr/strings.xml +++ b/presentation/src/main/res/values-fr/strings.xml @@ -1,5 +1,5 @@ - + --> + Nouvelle conversation Rédiger Raccourci désactivé Archivées Paramètres Notifications - Rechercher dans les conversations… + Thème + Rechercher dans les conversations… Entrer un nom ou un numéro Ignorer Continuer + Ajouter quelqu\'un Appeler Détails Enregistrer dans la galerie + Partager Ouvrir le tiroir de navigation %d sélectionnée Effacer @@ -40,11 +44,11 @@ Épingler en haut Désépingler Marquer comme lu - Marquer comme non lu + Marquer comme non-lu Bloquer - Synchronisation des messages… + Synchronisation des messages… Vous : %s - Brouillon + Brouillons Résultats dans les messages %d messages Vos conversations apparaîtront ici @@ -52,15 +56,12 @@ Vos conversations archivées apparaîtront ici Débuter une nouvelle conversation Réapprenez à aimer les textos - Faire de Message votre application SMS par défaut + Faire de QKSMS votre application SMS par défaut Changer Autorisation requise - Message a besoin de l\'autorisation d’envoyer et de consulter - des messages SMS - - Message a besoin de l\'autorisation d\'accéder aux - contacts - + QKSMS a besoin de l\'autorisation d’envoyer et de consulter des messages SMS + QKSMS a besoin de l\'autorisation d\'accéder aux contacts + QKSMS needs permission to display notifications Autoriser Boite de réception Archivées @@ -70,17 +71,25 @@ Paramètres Aide & commentaire Inviter des amis + Débloquer les nouvelles fonctions sensationnelles et soutenir le développement + Vous aimez QKSMS ? + Partagez un peu d’amour et évaluez-nous sur le Play Store ! + OK ! + ANNULER Supprimer - Êtes-vous sûr.e de vouloir supprimer cette conversation \? - Êtes-vous sûr.e de vouloir supprimer %d conversations \? - Êtes-vous sûr.e de vouloir supprimer %d conversations \? + Êtes-vous sûr de vouloir supprimer cette conversation ? + Êtes-vous sûr de vouloir supprimer %d conversations ? Copier le texte Transférer Supprimer + Choisir un numéro de téléphone + %s • Défaut + Une seule fois + Toujours %d sélectionnée %1$d sur %2$d résultats Envoyer en tant que message groupé @@ -89,8 +98,9 @@ Fiche du contact Programmé pour Le moment choisi doit être dans le futur ! + Vous devez déverrouiller QKSMS+ pour utiliser la programmation de message Ajouté aux messages programmés - Écrire un message… + Écrire un message… Copier le texte Transférer Supprimer @@ -114,14 +124,18 @@ Programmer un message Joindre un contact Erreur de lecture du contact + + SIM %1$d (%2$s) sélectionnée %s sélectionné, changer la carte SIM Envoyer un message - Envoi… + Envoi… Délivré %s Échec de l\'envoi. Appuyer pour réessayer Détails + Adresse copiée Titre de la conversation Notifications + Thème Archiver Désarchiver Bloquer @@ -132,30 +146,32 @@ Sauvegarde et restauration Sauvegarde des messages Restaurer à partir d\'une sauvegarde - Dernière sauvegarde - Chargement… + Chargement… Jamais + Backup location + Set folder Restauration Sélectionner une sauvegarde - Sauvegarde en cours… - Restauration en cours… + Déverrouillez QKSMS+ pour utiliser la sauvegarde et la restauration + Sauvegarde en cours… + Restauration en cours… Restaurer à partir d’une sauvegarde - Êtes-vous sûr de vouloir restaurer vos messages à partir de cette sauvegarde ? Arrêter la restauration Les messages qui ont déjà été restaurés resteront sur votre appareil + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details Sauvegardes Aucune sauvegarde trouvée - - %d message - %d messages - %d messages - Actuellement, seulement la sauvegarde et la restauration des SMS sont pris en charge. Les MMS et les sauvegardes planifiées arriveront bientôt ! Sauvegarder maintenant - Analyse de la sauvegarde… + Analyse de la sauvegarde… %d/%d messages - Enregistrement de la sauvegarde… - Synchronisation des messages… + Enregistrement de la sauvegarde… + Synchronisation des messages… Terminé ! Sauvegarder et restaurer Programmé @@ -175,10 +191,12 @@ Apparence Général Réponse QK + Thème Mode nuit Mode noir pur Heure de début Heure de fin + Couleurs de contact automatiques Taille de la police Utiliser la police du système Émoticône automatique @@ -189,6 +207,7 @@ Bouton 2 Bouton 3 Aperçus de notification + Réveiller l\'écran Vibration Son Aucun @@ -196,7 +215,7 @@ Fenêtre pour les nouveaux messages Appuyer pour annuler Appuyer en dehors de la fenêtre pour la fermer - Envoi différé + Envoi retardé Actions de balayage Configurer les actions de balayage pour les conversations Balayage droite @@ -219,10 +238,22 @@ Supprimer les accents des caractères lors de l\'envoi de messages SMS Numéros de mobile Lorsque vous composez un message, afficher uniquement les numéros de mobile + Supprimer les anciens messages automatiquement + Les messages seront supprimés après le nombre de jours spécifié + Nombre de jours + Jamais + Supprimer les anciens messages automatiquement ? + Si vous continuez, %1$d messages seront supprimés maintenant + + Après 1 jour + Après %d jours + + Envoyer les messages longs en MMS + Si vos messages texte plus longs ne parviennent pas à être envoyés, ou s\'ils sont envoyés dans le désordre, vous pouvez les envoyer sous forme de messages MMS à la place. Des frais supplémentaires peuvent s\'appliquer Compresser automatiquement les pièces jointes des MMS Synchroniser les messages Resynchroniser les messages avec la base de données Android native - À propos de Message + À propos de QKSMS Version %s Journal de débogage activé Journal de débogage désactivé @@ -234,6 +265,7 @@ Gestionnaire de blocage QKSMS Fonction de blocage intégrée dans QKSMS + Bloquer les spams, les numéros & les appels inconnus avec une liste noire & Planifier Filtrez automatiquement vos appels et vos messages dans un seul endroit pratique ! La communauté IQ™ vous permet d\'éviter les messages indésirables des spammeurs connus de celle-ci Filtrer automatiquement les messages de numéros non sollicités à l’aide de l’application « Devrais-je répondre » Copier les numéros bloqués @@ -249,14 +281,12 @@ Bloquer Débloquer - Continuer avec %s et bloquer ce numéro - Continuer avec %s et bloquer ces numéros - Continuer avec %s et bloquer ces numéros + Continuer à %s et bloquer ce numéro + Continuer à %s et bloquer ces numéros - Continuer avec %s et autoriser ce numéro - Continuer avec %s et autoriser ces numéros - Continuer avec %s et autoriser ces numéros + Continuer à %s et autoriser ce numéro + Continuer à %s et autoriser ces numéros À propos Version @@ -266,7 +296,39 @@ Contact Licence Droits d’auteur - Chargement… + Soutenir le développement, tout déverrouiller + Vous pouvez sauver un développeur affamé pour seulement %s + + Mise à niveau à vie pour %1$s %2$s + + Déverrouiller + faire un don pour %1$s %2$s + Merci de soutenir QKSMS ! + Vous avez maintenant accès à toutes les fonctionnalités de QKSMS+ + Une erreur s\'est produite. Merci de réessayer. + QKSMS + est gratuit pour les utilisateurs de F-Droid ! Si vous souhaitez soutenir le développement, n’hésitez pas à faire un don. + Faire un don avec PayPal + Prochainement + Thèmes premium + Débloquer de magnifiques couleurs de thèmes non disponibles dans la palette Material Design + Émoticône personnalisée + Créer des raccourcis d\'émoticône automatique personnalisée + Sauvegarde de message + Sauvegarder automatiquement vos messages. Plus de soucis de perdre son historique en cas de changement de téléphone ou de perte + Messages programmés + Messages programmés pour être automatiquement envoyés à une date et une heure spécifiques + Envoi retardé + Attendre quelques secondes avant d’envoyer votre message + Mode nuit automatique + Activer le mode nuit selon l’heure + Blocage avancé + Bloquer les messages qui contiennent les mots-clés ou correspondant à un modèle + Transfert automatique + Transférer automatiquement les messages de certains expéditeurs + Réponse automatique + Répondre automatiquement aux messages entrants avec une réponse prédéfinie + Plus + QKSMS est en cours de développement actif, et votre achat comprendra toutes les futures fonctionnalités QKSMS + ! + Chargement… Afficher plus de conversations Marquer comme lu Appeler @@ -274,6 +336,9 @@ Afficher plus Afficher moins Ouvrir la conversation + Material + HEX + Appliquer Aucune Archiver @@ -294,9 +359,9 @@ Annuler Copié Conversation archivée + Vous devez déverrouiller QKSMS+ pour utiliser cela Nouveau message - %s nouveaux messages %s nouveaux messages Message non envoyé @@ -319,10 +384,10 @@ Énorme - Aucun + Aucun retard 3 secondes - 5 secondes - 10 secondes + 5 secondes + 10 secondes Automatique @@ -348,82 +413,4 @@ LOL C\'est d\'accord - Auteurs - Vous devez déverrouiller QKSMS+ pour utiliser ceci - QKSMS est en développement actif, et votre achat inclura toutes les futures fonctionnalités de QKSMS+ ! - Plus - Répondre automatiquement aux messages entrants avec une réponse prédéfinie - Réponse automatique - Transférer automatiquement les messages de certains expéditeurs - Transfert automatique - Bloquer les messages qui contiennent des mots clés ou qui correspondent à des schémas - Blocage avancé - Activer le mode nuit en fonction de l\'heure du jour - Mode nuit automatique - Attendez quelques secondes avant d\'envoyer votre message - Délai d\'envoi - Programmer l\'envoi automatique de messages à une date et une heure précises - Messages programmés - Sauvegardez automatiquement vos messages. Ne craignez plus jamais de perdre votre historique si vous changez de téléphone ou si celui-ci est perdu - Sauvegarde des messages - Créer des raccourcis auto-emoji personnalisés - Auto-emoji personnalisé - Débloquez de magnifiques couleurs de thème non disponibles sur la palette Material Design - Thèmes premium - Prochainement - Donner via PayPal - QKSMS+ est gratuit pour les utilisateurs de F-Droid ! Si vous souhaitez soutenir le développement, un don serait très apprécié. - Vous avez maintenant accès à toutes les fonctionnalités de QKSMS+ - Merci de soutenir QKSMS ! - Débloquer + donner pour %1$s %2$s - Mise à niveau à vie pour %1$s %2$s - Vous pouvez sauver un développeur affamé pour seulement %s - Soutenir le développement, tout débloquer - Conditions d\'utilisation - Politique de confidentialité - Version de l\'application - Informations sur Message - Message - Impossible d\'ajouter du texte vide ! Merci de réessayer - Impossible d\'ajouter un numéro vide ! Merci de réessayer - D\'ACCORD ! - IGNORER - Partagez cet amour et évaluez nous sur Google Play ! - Vous aimez Message \? - Débloquez de formidables nouvelles fonctionnalités et soutenez le développement - Appliquer - HEX - Material - Une erreur est survenue, merci de réessayer - Bloquer les messages de spam ainsi que les numéros et appels inconnus avec la liste noire et la programmation - Si vos messages plus longs n\'arrivent pas à être envoyés ou sont envoyés dans le mauvais ordre, vous pouvez les envoyer en tant que MMS. Cela peut engendrer des frais supplémentaires - Envoyer les messages longs en MMS - - Au bout d\'1 jour - Au bout de %d jours - Au bout de %d jours - - Si vous confirmez, %1$d messages seront supprimés maintenant - Supprimer automatiquement les vieux messages \? - Jamais - Nombre de jours - Les messages seront supprimés après le nombre de jours défini - Supprimer automatiquement les vieux messages - Réveiller l\'écran - Couleur automatique des contacts - Thème - Débloquez QKSMS+ pour utiliser la sauvegarde et la restauration - Thème - Adresse copiée - SIM %1$d (%2$s) sélectionnée - Vous devez déverrouiller QKSMS+ pour pouvoir utiliser les messages programmés - Toujours - Juste cette fois - %s ∙ Par défaut - Sélectionnez un numéro de téléphone - Partager - Ajouter une personne - Thème - Message est dérivée de QKSMS - - Message est une application de messagerie open source remplaçant l\'application d\'origine sur Android. diff --git a/presentation/src/main/res/values-gd/e_strings.xml b/presentation/src/main/res/values-gd/e_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..d596b4b46481eea495ab12929387f35c4c234b28 --- /dev/null +++ b/presentation/src/main/res/values-gd/e_strings.xml @@ -0,0 +1,27 @@ + + + + Teachdaireachd + Suidhich “Teachdaireachd” ’nad aplacaid SMS bhunaiteach + Feumaidh “Teachdaireachd” cead gus teachdaireachdan SMS a chur ’s a shealltainn + Feumaidh “Teachdaireachd” cead gus an luchd-aithne agad a shealltainn + Fiosrachadh mu “Teachdaireachd” + Tionndadh na h-aplacaid + Poileasaidh prìobhaideachd + Teirmichean na seirbheise + Ùghdaran + \ No newline at end of file diff --git a/presentation/src/main/res/values-gd/strings.xml b/presentation/src/main/res/values-gd/strings.xml index 77861cd0d0763bd9be8d1712bdd6fb549aa291b7..ea60013985cecd616049b6aef30eb55293c6fdf1 100644 --- a/presentation/src/main/res/values-gd/strings.xml +++ b/presentation/src/main/res/values-gd/strings.xml @@ -1,291 +1,426 @@ + - Bun-tùs - Tionndadh - Aisig o lethbhreac-glèidhidh - ’Ga aiseag… - A’ dèanamh lethbhreac-glèidhidh… - Tagh lethbhreac-glèidhidh - Aisig - Chan ann idir - ’Ga luchdadh… - An lethbhreac-glèidhidh mu dheireadh - ’Ga aiseag o lethbhreac-glèidhidh - A’ dèanamh lethbhreac-glèidhidh dhe na teachdaireachdan - Lethbhreacan-glèidhidh ’s aiseag - Chaidh a shàbhaladh sa ghailearaidh - Cha b’ urrainn dhuinn am meadhan a luchdadh - Sguab às an còmhradh - Na bac tuilleadh - Bac - Thoir às an tasg-lann - Cuir san tasg-lann - Brathan - Tiotal a’ chòmhraidh - Mion-fhiosrachadh - Cha deach a chur. Thoir gnogag airson feuchainn ris a-rithist - Air a lìbhrigeadh %s - ’Ga chur… - Cuir teachdaireachd - Chaidh %s a thaghadh, atharraich a’ chairt SIM - Mearachd a’ leughadh an neach-aithne - Ceangail neach-aithne ris - Cuir teachdaireachd air an sgeideal - Tog dealbh - Ceangail dealbh ris - Cuir ceanglachan ris - Còd na mearachd: %d - Air lìbhrigeadh: %s - Air fhaighinn: %s - Air a chur: %s - Meud: %s - Prìomhachas: %s - Cuspair: %s - Gu: %s - O: %s - Seòrsa: %s - Mion-fhiosrachadh mun teachdaireachd - Falamhaich - Air adhart - Air ais - Sguab às - Sìn air adhart - Dèan lethbhreac dhen teacsa - Sgrìobh teachdaireachd… - Cuir ris na teachdaireachdan sgeidealaichte - Feumaidh a t-àm a thagh thu a bhith san àm ri teachd! - Air an sgeideal - Cairt-chonaltraidh - Seo toiseach a’ chòmhraidh. Can rudeigin càilear! - Chì a h-uile duine na faightearan ’s na freagairtean - Cuir mar theachdaireachd buidhinn - %1$d à %2$d toradh - Chaidh %d a thaghadh + New conversation + Compose + Shortcut disabled + Archived + Settings + Notifications + Theme + Search inbox… + Type a name or number + Skip + Continue + Add person + Call + Details + Save to gallery + Share + Open navigation drawer + %d selected + Clear + Archive + Unarchive + Delete + Add to contacts + Pin to top + Unpin + Mark read + Mark unread + Block + Syncing messages… + You: %s + Draft + Results in messages + %d messages + Your conversations will appear here + No results + Your archived conversations will appear here + Start new conversation + Love texting again + Make QKSMS your default SMS app + Change + Permission required + QKSMS needs permission to send and view SMS messages + QKSMS needs permission to view your contacts + QKSMS needs permission to display notifications + Allow + Inbox + Archived + Scheduled + Blocking + More + Settings + Help & feedback + Invite friends + Unlock amazing new features, and support development + Enjoying QKSMS? + Share some love and rate us on Google Play! + OKAY! + DISMISS + Delete - A bheil thu cinnteach gu bheil thu airson %d chòmhradh a sguabadh às\? - A bheil thu cinnteach gu bheil thu airson %d chòmhradh a sguabadh às\? - A bheil thu cinnteach gu bheil thu airson %d còmhraidhean a sguabadh às\? - A bheil thu cinnteach gu bheil thu airson %d còmhradh a sguabadh às\? + Are you sure you would like to delete this conversation? + Are you sure you would like to delete %d conversations? + Are you sure you would like to delete %d conversations? + Are you sure you would like to delete %d conversations? - Sguab às - Thoir cuireadh do charaidean - Cobhair ⁊ beachdan - Roghainnean - Barrachd - ’Ga bhacadh - Sgeidealaichte - San tasglann - Am bogsa a-steach - Ceadaich - Feumaidh “Teachdaireachd” cead gus an luchd-aithne agad a shealltainn - Feumaidh “Teachdaireachd” cead gus teachdaireachdan SMS a chur ’s a shealltainn - Tha feum air cead - Atharraich - Suidhich “Teachdaireachd” ’nad aplacaid SMS bhunaiteach - Tòisich air còmhradh ùr - Nochdaidh na còmhraidhean san tasg-lann agad an-seo - Gun toradh - Nochdaidh na còmhraidhean agad an-seo - %d teachdaireachd(an) - Toraidhean sna teachdaireachdan - Dreachd: %s - Thusa: %s - A’ sioncronachadh nan teachdaireachdan… - Bac - Cuir comharra nach deach a leughadh - Cuir comharra gun deach a leughadh - Dì-phrìnich - Prìnich ris a’ bhàrr - Cuir ris an luchd-aithne - Sguab às - Thoir às an tasg-lann - Cuir san tasg-lann - Falamhaich - Chaidh %d a thaghadh - Fosgail drathair na seòladaireachd - Sàbhail dhan ghailearaidh - Mion-fhiosrachadh - Cuir fòn - Lean air adhart - Leum thairis air - Sgrìobh ainm no àireamh - Lorg sa bhogsa a-steach… - Brathan - Roghainnean - San tasglann - Tha an ath-ghoirid à comas - Sgrìobh - Còmhradh ùr - Teachdaireachd - - %d teachdaireachd - %d theachdaireachd - %d teachdaireachdan - %d teachdaireachd + + Copy text + Forward + Delete + + Choose a phone number + %s ∙ Default + Just once + Always + %d selected + %1$d of %2$d results + Send as group message + Recipients and replies will be visible to everyone + This is the start of your conversation. Say something nice! + Contact card + Scheduled for + Selected time must be in the future! + You must unlock QKSMS+ to use scheduled messaging + Added to scheduled messages + Write a message… + Copy text + Forward + Delete + Previous + Next + Clear + Message details + Type: %s + From: %s + To: %s + Subject: %s + Priority: %s + Size: %s + Sent: %s + Received: %s + Delivered: %s + Error code: %d + Add an attachment + Attach a photo + Take a photo + Schedule message + Attach a contact + Error reading contact + + SIM %1$d (%2$s) selected + %s selected, change SIM card + Send message + Sending… + Delivered %s + Failed to send. Tap to try again + Details + Address copied + Conversation title + Notifications + Theme + Archive + Unarchive + Block + Unblock + Delete conversation + Couldn\'t load media + Saved to gallery + Backup and restore + Backing up messages + Restoring from backup + Loading… + Never + Backup location + Set folder + Restore + Select a backup + Please unlock QKSMS+ to use backup and restore + Backup in progress… + Restore in progress… + Restore from backup + Stop restore + Messages that have already been restored will remain on your device + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details + Backups + No backups found + Currently, only SMS is supported by Backup and Restore. MMS support and scheduled backups will be coming soon! + Backup now + Parsing backup… + %d/%d messages + Saving backup… + Syncing messages… + Finished! + Backup and restore + Scheduled + Automatically send a message, at the exact moment you\'d like + Hey! When was your birthday again? + It\'s on December 23rd + Happy birthday! Look at what a great friend I am, remembering your birthday + + Sending on December 23rd  + Schedule a message + Scheduled message + + Send now + Copy text + Delete + + Appearance + General + QK Reply + Theme + Night mode + Pure black night mode + Start time + End time + Automatic contact colors + Font size + Use system font + Automatic emoji + Notifications + Tap to customize + Actions + Button 1 + Button 2 + Button 3 + Notification previews + Wake screen + Vibration + Sound + None + QK Reply + Popup for new messages + Tap to dismiss + Tap outside of the popup to close it + Delayed sending + Swipe actions + Configure swipe actions for conversations + Right swipe + Left swipe + CHANGE + + None + Archive + Delete + Block + Call + Mark read + Mark unread + + Delivery confirmations + Confirm that messages were sent successfully + Signature + Add a signature to the end of your messages + Strip accents + Remove accents from characters in outgoing SMS messages + Mobile numbers only + When composing a message, only show mobile numbers + Delete old messages automatically + Messages will be deleted after the specified number of days + Number of days + Never + Delete old messages automatically? + If you proceed, %1$d messages will be deleted now + + After 1 day + After %d days + After %d days + After %d days - Ùghdaran - Dh’fhàillig cur na teachdaireachd gu %s - Cha deach an teachdaireachd a chur - - %s teachdaireachd ùr - %s theachdaireachd ùr - %s teachdaireachdan ùra - %s teachdaireachd ùr + Send long messages as MMS + If your longer text messages are failing to send, or sending in the wrong order, you can send them as MMS messages instead. Additional charges may apply + Auto-compress MMS attachments + Sync messages + Re-sync your messages with the native Android SMS database + About QKSMS + Version %s + Debug logging enabled + Debug logging disabled + Enter duration (seconds) + Blocking + Drop messages + Drop incoming messages from blocked senders instead of hiding them + Blocked conversations + Blocking Manager + QKSMS + Built-in blocking functionality in QKSMS + Block spam messages, numbers & unknown calls with blacklist & Schedule + Automatically filter your calls and messages in one convenient place! Community IQ™ allows you to prevent unwanted messages from community known spammers + Automatically filter messages from unsolicited numbers by using the \"Should I Answer\" app + Copy blocked numbers + Continue to %s and copy over your existing blocked numbers + Blocked numbers + Your blocked numbers will appear here + Block a new number + Block texts from + Phone number + Block + Blocked messages + Your blocked messages will appear here + Block + Unblock + + Continue to %s and block this number + Continue to %s and block these numbers + Continue to %s and block these numbers + Continue to %s and block these numbers - Còmhradh san tasglann - Chaidh lethbhreac dheth a dhèanamh - Neo-dhèan - Suidhich - Barrachd - Cuir stad air - Sàbhail - Sguab às - Sguir dheth - Lean air adhart - Tha - Feumaidh tu a’ ghlas a thoirt far QKSMS+ mus cleachd thu seo - Fosgail an còmhradh - Seall nas lugha - Seall barrachd - Sguab às - Cuir fòn - Cuir comharra gun deach a leughadh - Seall barrachd chòmhraidhean - ’Ga luchdadh… - Tha sinn a’ cumail a’ dol le leasachadh QKSMS agus gabhaidh a’ cheannachd agad a-staigh gleus sam bith a thèid a chur ri QKSMS+ fhathast! - Cuir teacsaichean le tlachd - Barrachd - Freagair do theachdaireachdan a thig a-steach gu fèin-obrachail le freagairt ro-shuidhichte - Freagair gu fèin-obrachail - Sìn air adhart teachdaireachdan o sheòladairean sònraichte - Sìneadh air adhart fèin-obrachail - Bac teachdaireachdan anns a bheil faclan sònraichte no a fhreagras ri pàtranan - Bacadh adhartach - Cuir am modh oidhche an comas a-rèir àm dhen latha - Modh oidhche fèin-obrachail - Fuirich diog no dhà mus dèid an teachdaireachd agad a chur - Dàil air a’ chur - Cuir teachdaireachdan air an sgeideal ach an dèid an cur gu fèin-obrachail aig a’ cheann-là ’s àm a thagh thu - Teachdaireachdan sgeidealaichte - Dèan lethbhreacan-glèidhidh dhe na teachdaireachdan agad gu fèin-obrachail. Na bhiodh dragh ort a-rithist mu call na h-eachdraidh ma dh’atharraicheas tu gu fòn eile no ma chailleas tu am fòn agad - Lethbhreacan-glèidhidh dhe na teachdaireachdan - Cruthaich ath-ghoiridean gnàthaichte airson Emojis fèin-obrachail - Emojis fèin-obrachail gnàthaichte - Thoir a’ ghlas far dathan ùrlair bòidheach nach eil ri fhaighinn air pailead Material Design - Ùrlaran premium - A’ tighinn a dh’aithghearr - Thoir tabhartas dhuinn le PayPal - Tha QKSMS+ saor ’s an-asgaidh cha luchd-chleachdaidh F-Droid! Nam bu mhiann leat taic a thoirt dhan obair-leasachaidh, bhithinn glè thaingeil air tabhartas. - Tha cothrom agad a-nis dhan a h-uile gleus QKSMS+ - Mòran taing airson taic a thoirt do QKSMS! - Thoir a’ ghlais dheth ⁊ thoir tìodhlac dhuinn air %1$s %2$s - Àrdachadh fad beatha air %1$s %2$s - ’S urrainn dhut taic a thoirt do bhith-beò luchd-leasachaidh air %s a-mhàin - Cuir taic ris an leasachadh, thoir a’ ghlas far a h-uile càil - Teirmichean na seirbheise - Poileasaidh prìobhaideachd - Tionndadh na h-aplacaid - Fiosrachadh mu “Teachdaireachd” - Còir-lethbhreac - Ceadachas - Mu dhèidhinn - Lean air adhart gu %s ’s ceadaich an àireamh seo - Lean air adhart gu %s ’s ceadaich na h-àireamhan seo - Lean air adhart gu %s ’s ceadaich na h-àireamhan seo - Lean air adhart gu %s ’s ceadaich na h-àireamhan seo + Continue to %s and allow this number + Continue to %s and allow these numbers + Continue to %s and allow these numbers + Continue to %s and allow these numbers - - Lean air adhart gu %s ’s bac an àireamh seo - Lean air adhart gu %s ’s bac na h-àireamhan seo - Lean air adhart gu %s ’s bac na h-àireamhan seo - Lean air adhart gu %s ’s bac na h-àireamhan seo + About + Version + Developer + Source code + Changelog + Contact + License + Copyright + Support development, unlock everything + You can save a starving developer for just %s + + Lifetime upgrade for %1$s %2$s + + Unlock + donate for %1$s %2$s + Thank you for supporting QKSMS! + You now have access to all QKSMS+ features + An error has occurred, please try again + QKSMS+ is free for F-Droid users! If you\'d like to support development, a donation would be highly appreciated. + Donate via PayPal + Coming soon + Premium themes + Unlock beautiful theme colors not available on the Material Design palette + Custom auto-emoji + Create custom auto-emoji shortcuts + Message backup + Automatically back up your messages. Never again worry about losing your history if you change phones or your phone gets lost + Scheduled messages + Schedule messages to automatically be sent at a specific time and date + Delayed sending + Wait a few seconds before sending your message + Automatic night mode + Enable night mode based on the time of day + Advanced blocking + Block messages that contain keywords or match patterns + Auto-forward + Automatically forward messages from certain senders + Auto-respond + Automatically respond to incoming messages with a preset response + More + QKSMS is under active development, and your purchase will include all future QKSMS+ features! + Loading… + View more conversations + Mark read + Call + Delete + Show more + Show less + Open conversation + Material + HEX + Apply + + None + Archive + Delete + Block + Call + Mark read + Reply + + Yes + Continue + Cancel + Delete + Save + Stop + More + Set + Undo + Copied + Archived conversation + You must unlock QKSMS+ to use this + + New message + %s new messages + %s new messages + %s new messages - Na bac tuilleadh - Bac - Nochdaidh na teachdaireachdan a bhac thu an-seo - Teachdaireachdan bacte - Bac - Àireamh fòn - Bac teacsaichean o - Bac àireamh ùr - Nochdaidh na h-àireamhan a bhac thu an-seo - Àireamhan bacte - Lean air adhart gu %s ’s cuir lethbhreac dhe na h-àireamhan a bhac thu ann - Dèan lethbhreac de na h-àireamhan bacte - Criathraich teachdaireachdan o àireamhan gun iarraidh leis an aplacaid “Am bu chòir dhomh freagairt\?” - Criathraich na gairmean ’s na teachdairean agad còmhla ’s gu fèin-obrachail! Le Community IQ™, ’s urrainn dhut teachdaireachdan gun iarraidh a bhacadh a thig o luchd-spama air a bheil a’ choimhearsnachd eòlach - Gleus bacaidh am broinn QKSMS - QKSMS - Manaidsear a’ bhacaidh - Còmhraidhean ’gam bacadh - Tilg air falbh na teachdaireachdan o sheòladairean bacte seach am falach - Tilg air falbh teachdaireachdan - Bacadh - Cuir a-steach faide (diog) - Tha logadh an dì-bhugachaidh à comas - Tha logadh an dì-bhugachaidh an comas - Tionndadh %s - Ath-shioncronaich na teachdaireachdan agad le stòr-dàta SMS Android tùsail - Sioncronaich na teachdaireachdan - Dùmhlaich ceanglachain MMS gu fèin-obrachail - Nuair a bhios mi ri sgrìobhadh teachdaireachd, na seall ach àireamhan mobile - Àireamhan mobile a-mhàin - Thoir na stràcan fo bhàrr charactaran ann an teachdaireachdan SMS a-mach - Rùisg às na stràcan - Cruthaich eàrr-sgrìobhaidh a thèid a chur ri bonn nan teachdaireachdan agad - Eàrr-sgrìobhadh - Dearbh gun deach teachdaireachdan a chur - Dearbhaidhean lìbhrigidh - ATHARRAICH - Grad-shlaighdeadh gu clì - Grad-shlaighdeadh gu deas - Rèitich gnìomhan grad-shlaighdidh dha na còmhraidhean - Gnìomhan grad-shlaighdidh - Dàil air a’ chur - Thoir gnogag taobh a-muigh na priob-uinneige gus a leigeil seachad - Thoir gnogag ’ga leigeil seachad - Priob-uinneag airson teachdaireachdan ùra - Freagairt QK - Chan eil gin - Fuaim - Crith - Ro-sheallaidhean air brathan - Putan 3 - Putan 2 - Putan 1 - Gnìomhan - Thoir gnogag airson a ghnàthachadh - Brathan - Emoji fèin-obrachail - Cleachd cruth-clò an t-siostaim - Meud a’ chrutha-chlò - Àm crìochnachaidh - Àm tòiseachaidh - Modh oidhche dubh - Modh oidhche - Freagairt QK - Coitcheann - Coltas - Teachdaireachd sgeidealaichte - Cuir teachdaireachd air an sgeideal - Thèid a chur an 23mh dhen Dùbhlachd  - Co-latha-breith sona! Nach e caraid math a th’ annam a’ cuimhneachadh a’ cho-là breith agad - Tha an 23mh dhen Dùbhlachd - Nise, cuin a tha an co-là breith agad a-rithist\? - Cuir teachdaireachd gu fèin-obrachail aig an dearbh àm a thogras tu - Sgeidealaichte - Lethbhreacan-glèidhidh ’s aiseag - Deiseil! - A’ sioncronachadh nan teachdaireachdan… - A’ sàbhaladh an lethbhric-ghlèidhidh… - %d/%d teachdaireachd(an) - A’ parsadh an lethbhric-ghlèidhidh… - Dèan lethbhreac-glèidhidh an-dràsta - Aig an àm seo, cha chuir lethbhreacan-glèidhidh ’s aiseag taic ach ri SMA. Tha taic ri MMS is sgeidealachadh nan lethbhreacan-glèidhidh ri thighinn a dh’aithghearr! - Cha deach lethbhreac-glèidhidh a lorg - Lethbhreacan-glèidhidh - Fuirichidh na teachdaireachdan a dh’aisig thu mu thràth air an uidheam agad - Cuir stad air an aiseag - A bheil thu cinnteach gu bheil thu airson na teachdaireachdan agad aiseag on lethbhreac-ghlèidhidh seo\? - \ No newline at end of file + Message not sent + The message to %s failed to send + + System + Disabled + Always on + Automatic + + + Show name and message + Show name + Hide contents + + + Small + Normal + Large + Larger + + + No delay + 3 seconds + 5 seconds + 10 seconds + + + Automatic + 100KB + 200KB + 300KB + 600KB + 1000KB + 2000KB + No compression + + + Okay + Give me a moment + On my way + Thanks + Sounds good + What\'s up? + Agreed + No + Love you + Sorry + LOL + That\'s okay + + diff --git a/presentation/src/main/res/values-gl/e_strings.xml b/presentation/src/main/res/values-gl/e_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..29e682611af22ef2567c2b8bd49b49a265ba4e7b --- /dev/null +++ b/presentation/src/main/res/values-gl/e_strings.xml @@ -0,0 +1,27 @@ + + + + Mensaxe + Faga de Mensaxe o seu aplicativo SMS por defecto + Mensaxe necesita permiso para enviar e ver mensaxes SMS + Mensaxe necesita permiso para ver os seus contactos + Información da mensaxe + Versión do aplicativo + Política de privacidade + Termos do servizo + Autores + \ No newline at end of file diff --git a/presentation/src/main/res/values-gl/strings.xml b/presentation/src/main/res/values-gl/strings.xml deleted file mode 100644 index f96be31c0d363d17c4cafe1a450a2c531ed47eb9..0000000000000000000000000000000000000000 --- a/presentation/src/main/res/values-gl/strings.xml +++ /dev/null @@ -1,281 +0,0 @@ - - - Autores - A mensaxe para %s fallou ao enviarse - Mensaxe non enviada - - Nova mensaxe - %s novas mensaxes - - Conversa arquivada - Copiada - Desfacer - Establecer - Máis - Deter - Gardar - Eliminar - Cancelar - Continuar - Si - Debe desbloquear QKSMS+ para usar isto - Abrir conversa - Amosar menos - Amosar máis - Eliminar - Chamar - Marcada como lida - Ver máis conversas - Cargando… - Este aplicativo está a ser desenvolvido e a súa compra inclúe todas as futuras funcionalidades de QKSMS+! - Máis - Enviar automaticamente unha resposta tendo por base os modelos - Resposta automática - Reenviar automaticamente as mensaxes dalgúns remitentes - Reenvío automático - Bloquear mensaxes a través de claves ou patróns - Bloqueo avanzado - Habilitar modo nocturno automaticamente conforme a hora do día - Modo nocturno automático - Agarde uns poucos segundos antes de enviar a súa mensaxe - Atraso no envío - Programar mensaxes para ser enviadas automaticamente nunha data e hora específicas - Mensaxes programadas - Fai unha copia de seguridade das túas mensaxes automaticamente. Nunca máis te preocupes por perder o teu historial se cambias de teléfono ou se o perdes - Copia de seguranza das mensaxes - Crear atallos personalizados para as emoticonas - Emoticona personalizada - Desbloquear diversos temas non dispoñibles na paleta Material Design - Temas premium - Proximamente - Doar a través de PayPal - QKSMS + é gratuíto para usuarios de F-Droid. Se desexa apoiar o desenvolvemento, agradeceríase moito unha doazón. - Agora ten acceso a todos os recursos do QKSMS+ - Grazas por apoiar QKSMS! - Desbloquear + cunha doazón de %1$s %2$s - Confirmacións de entrega - Actualización vitalicia por %1$s %2$s - Podes salvar a un desenvolvedor famento por só %s - Apoie o desenvolvemento, desbloquee todo - Termos do servizo - Política de privacidade - Versión do aplicativo - Información da mensaxe - Dereitos de autor - Licenza - Código fonte - Versión - Sobre - - Continuar a %s e permitir este número - Continuar a %s e permitir este números - - - Continuar a %s e bloquear este número - Continuar a %s e bloquear estes números - - Desbloquear - Bloquear - As túas mensaxes bloqueadas aparecerán aquí - Mensaxes bloqueadas - Bloquear - Número de teléfono - Bloquear mensaxes de - Bloquear un novo número - Os teus números bloqueados aparecerá aquí - Números bloqueados - Continuar para %s e substituír os números bloqueados - Copiar números bloqueados - Filtrar automaticamente as mensaxes de números non solicitados mediante o aplicativo \"Debería responder\" - Filtra automaticamente as túas chamadas e mensaxes nun lugar conveniente. Community IQ ™ permítelle evitar mensaxes non desexadas de persoas que envían correos lixo coñecidos na comunidade - Funcionalidade de bloqueo, nativa no QKSMS - QKSMS - Xestor de bloqueos - Conversas bloqueadas - As mensaxes enviadas polos remitentes bloqueados serán descartadas e non agochadas - Descartar mensaxes - Bloqueando - Inserir duración (segundos) - Depuración desactivada - Depuración activada - Versión %s - Resincronizar as túas mensaxes cunha base de datos nativa de SMS - Sincronizar mensaxes - Comprimir anexos MMS automaticamente - Ao escribir unha mensaxe, mostrar só os números móbiles - Só números deteléfono - Eliminar acentos desde as características en mensaxes SMS enviadas - Eliminar acentos - Engadir unha sinatura á fin das túas mensaxes - Sinatura - Confirmar cando as mensaxes se envíen con éxito - As mensaxes que xa se restauraron permanecerán no teu dispositivo - CAMBIAR - Deslizar á esquerda - Deslizar á dereita - Configurar as accións de deslizar para conversas - Accións de deslizar - Atraso no envío - Premer fóra do elemento emerxente para pechalo - Prema para descartar - Elementos emerxentes para novas mensaxes - Responder a través de QK - Ningún - Son - Vibración - Previsualización das notificacións - Botón 3 - Botón 2 - Botón 1 - Accións - Prema para personalizar - Notificacións - Emoticona automática - Usar a fonte do sistema - Tamaño da letra - Hora do fin - Hora de inicio - Modo nocturno escuro puro - Modo nocturno - Responder a través de QK - Xeral - Apariencia - Mensaxe programada - Programar unha mensaxe - Enviar o día 23 de Decembro  - Parabéns! Mira que bo amigo son, recordando o teu aniversario - É o 23 de Decembro - Ola! Cando é o teu aniversario\? - Enviar automaticamente unha mensaxe á hora especificada - Programado - Facer copia de seguranza e restaurar - Finalizado! - Sincronizando mensaxes… - Gardando copia de seguranza… - %d/%d mensaxes - Analizando a copia de seguranza… - Facer copia de seguranza agora - Actualmente, a copia de seguranza e a restauración só admiten SMS. O soporte MMS e as copias de seguranza programadas chegarán en breve! - - Non hai mensaxes - %d mensaxes - - Non se atopou ningunha copia de seguranza - Copias de seguranza - Deter restauración - Ten a certeza de que quere restaruar as túas mensaxes desde esta copia de seguranza\? - Restaurar desde a copia de seguranza - Restauración en progreso… - Copia de seguranza en progreso… - Seleccionar unha copia de seguranza - Restaurar - Nunca - Cargando… - Última copia de seguranza - Facendo unha copia de seguranza das mensaxes - Restaurar desde a copia de seguranza - Copia de seguranza e restauración - Gardado na galería - Non puido cargar multimedia - Eliminar conversa - Desbloquear - Bloquear - Desarquivar - Arquivar - Niotificacións - Título da conversa - Detalles - Fallou ao enviar. Prema para intentar de novo - Entregado %s - Enviando… - Enviar mensaxe - %s seleccionado, cambiar tarxeta SIM - Erro ao ler contacto - Anexar un contacto - Programar mensaxe - Tomar unha foto - Anexar unha foto - Engadir un anexo - Código do erro: %d - Entregado: %s - Recibido: %s - Enviado: %s - Tamaño: %s - Prioridade: %s - Asunto: %s - Para: %s - De: %s - Tipo: %s - Detalles da mensaxe - Limpar - Posterior - Anterior - Eliminar - Reenviar - Copiar texto - Escribir unha mensaxe… - Engadido ás mensaxes programadas - A hora escollida ten que ser futura! - Programado para - Tarxeta de contacto - Este é o inicio da túa conversa. Di algo lindo! - Os destinatarios e respostas serán visibles para todos - Enviar como unha mensaxe de grupo - %1$d de %2$d resultados - %d seleccionada(s) - - Ten a certeza de querer eliminar esta conversa\? - Ten a certeza de querer eliminar %d conversas\? - - Eliminar - Invitar amigos - Axuda & comentarios - Configuración - Máis - Bloqueadas - programadas - Arquivadas - Caixa de entrada - Permitir - Mensaxe necesita permiso para ver os seus contactos - Mensaxe necesita permiso para enviar e ver mensaxes SMS - Permiso requirido - Cambiar - Faga de Mensaxe o seu aplicativo SMS por defecto - Encántame enviar mensaxes de texto outra vez - Comezar nova conversa - As conversas arquivadas aparecerán aquí - Non hai resultados - As túas conversas aparecerá aquí - %d mensaxes - Resultados nas mensaxes - Borrador: %s - Ti: %s - Sincronizando mensaxes… - Bloquear - Marca como non lida - Marcada como lida - Desfixar - Fixar enriba - Engadir a Contactos - Eliminar - Non arquivar - Arquivar - Eliminar - %d seleccionada(s) - Abrir menú de navegación - Gardar en galería - Detalles - Chamar - Continuar - Omitir - Escribe un nome ou número - Buscar caixa de entrada… - Notificacións - Configuración - Arquivada - Atallo desactivado - Escribir - Nova conversa - Mensaxe - \ No newline at end of file diff --git a/presentation/src/main/res/values-hi/strings.xml b/presentation/src/main/res/values-hi/strings.xml index d9e3c3e4067ae2eba3a253c763198e0730c0ac08..7091372a6527dac0af2c3114fb513faebac772d0 100644 --- a/presentation/src/main/res/values-hi/strings.xml +++ b/presentation/src/main/res/values-hi/strings.xml @@ -1,5 +1,4 @@ - + सिम %1$d (%2$s) चयनित + %s चयनित, सिम कार्ड बदलें संदेश भेजें भेज रहा है… %s वितरित भेजने में असफल। पुनः प्रयास करें विवरण - Conversation title + पता कॉपी किया गया + वार्तालाप शीर्षक अधिसूचनाएँ + थीम संग्रह - Unarchive + संग्रह से निकालें अवरुदध करें - Unblock + अनब्लॉक करें वार्तालाप मिटाऐं - Couldn\'t load media + मीडिया लोड नहीं हो सका गैलरी मैं सेव किया गया है - Backup and restore - Backing up messages - Restoring from backup - पिछला बेकप + बैकअप और पुनर्स्थापना + संदेशों का बैकअप लेना + बैकअप से रीस्टोर करें लोड हो रहा है... कभी नहीं - Restore + Backup location + Set folder + पुनर्स्थापित किसी बैकअप का चयन करें - Please unlock QKSMS+ to use backup and restore + बैकअप का उपयोग करने और पुनर्स्थापित करने के लिए कृपया QKSMS+ अनलॉक करें Backup in progress… - Restore in progress… - Restore from backup - Are you sure you would like to restore your messages from this backup? - Stop restore - Messages that have already been restored will remain on your device + पुनःस्थापन प्रगति में… + बैकअप से रीस्टोर करें + पुनर्स्थापना बंद करो + संदेश जो पहले ही बहाल हो चुके हैं वे आपके डिवाइस पर बने रहेंगे + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details बैकअप कोई बैकअप नहीं मिला - - %d संदेश - %d संदेशें - वर्तमान में, केवल एसएमएस बैकअप और बहाल द्वारा समर्थित है| एमएमएस समर्थन और अनुसूचित बैकअप जल्द ही आ रहा है! अभी बैकअप लें बैकअप पदच्छेद हो रहा है... @@ -169,71 +185,87 @@ निर्धारित संदेश अभी भेजें - Copy text - Delete + टेक्स्ट कॉपी करें + मिटाएँ दिखावट सामान्य QK उत्तर + थीम रात्रि अंदाज़ शुद्ध काली रात अंदाज़ शुरुआत समय अंत समय + स्वचालित संपर्क रंग लिखाई का आकर यंत्र ध्वनियां उपयोग करें - Automatic emoji + स्वचालित इमोजी सूचनाएं - Tap to customize + अनुकूलित करने के लिए टैप करें कार्रवाई बटन एक बटन दो बटन तीन अधिसूचना सेटिंग्स + Wake screen कंपन ध्वनियाँ कुछ नहीं QK जवाब - Popup for new messages - Tap to dismiss - Tap outside of the popup to close it - Delayed sending - Swipe actions - Configure swipe actions for conversations + नए संदेशों के लिए पॉपअप + खारिज करने के लिए टैप करें + पॉपअप को बंद करने के लिए उसके बाहर टैप करें + विलंबित भेजें + स्वाइप क्रिया + बातचीत के लिए स्वाइप कार्रवाइयां कॉन्फ़िगर करें दाहिने तरफ से खींचे बायें तरफ से खींचे बदलें - None + कोई नहीं संग्रह मिटायें - Block - Call - Mark read - Mark unread + अवरुदध करें + कॉल + पढ़ा गया मार्क करें + अपठित चिह्नित करें वितरण पुष्टि - Confirm that messages were sent successfully - Signature - Add a signature to the end of your messages + पुष्टि करें कि संदेश सफलतापूर्वक भेजे गए थे + हस्ताक्षर + अपने संदेशों के अंत में एक हस्ताक्षर जोड़ें Strip accents - Remove accents from characters in outgoing SMS messages - Mobile numbers only - When composing a message, only show mobile numbers - Auto-compress MMS attachments - Sync messages - Re-sync your messages with the native Android SMS database - About QKSMS + आउटगोइंग एसएमएस संदेशों में वर्णों से उच्चारण हटाएं + केवल मोबाइल नंबर + संदेश लिखते समय केवल मोबाइल नंबर दिखाएं + पुराने संदेशों को स्वचालित रूप से हटाएं + निर्दिष्ट दिनों के बाद संदेश हटा दिए जाएंगे + दिनों की संख्या + कभी नहीं + पुराने संदेशों को स्वचालित रूप से हटाएं? + अगर आप आगे बढ़ते हैं, तो %1$d संदेशों को अभी हटा दिया जाएगा + + 1 दिन के बाद + %d दिनों के बाद + + एमएमएस के रूप में लंबे संदेश भेजें + यदि आपके लंबे टेक्स्ट संदेश गलत क्रम में भेजने या भेजने में विफल हो रहे हैं, तो आप उन्हें इसके बजाय एमएमएस संदेशों के रूप में भेज सकते हैं। अतिरिक्त शुल्क लागू हो सकते हैं + एमएमएस अनुलग्नकों को स्व-संपीड़ित करें + संदेशों को समन्वयित करें + अपने संदेशों को मूल एंड्रॉइड एसएमएस डेटाबेस के साथ पुन: समन्वयित करें + QKSMS के बारे में संस्करण %s Debug logging enabled Debug logging disabled - Enter duration (seconds) - Blocking - Drop messages - Drop incoming messages from blocked senders instead of hiding them - Blocked conversations - Blocking Manager + अवधि दर्ज करें (सेकंड) + अवरुद्ध + संदेश छोड़ें + आने वाले संदेशों को छिपाने के बजाय अवरुद्ध प्रेषकों से ड्रॉप करें + अवरुद्ध बातचीत + अवरोध प्रबंधक QKSMS - Built-in blocking functionality in QKSMS + QKSMS में अंतर्निहित अवरोधन कार्यक्षमता + Block spam messages, numbers & unknown calls with blacklist & Schedule Automatically filter your calls and messages in one convenient place! Community IQ™ allows you to prevent unwanted messages from community known spammers Automatically filter messages from unsolicited numbers by using the \"Should I Answer\" app Copy blocked numbers @@ -242,12 +274,12 @@ Your blocked numbers will appear here Block a new number Block texts from - Phone number - Block - Blocked messages - Your blocked messages will appear here - Block - Unblock + फ़ोन नंबर + अवरुदध करें + अवरुद्ध संदेश + आपके अवरुद्ध संदेश यहां दिखाई देंगे + अवरुदध करें + अनब्लॉक करें Continue to %s and block this number Continue to %s and block these numbers @@ -256,14 +288,15 @@ Continue to %s and allow this number Continue to %s and allow these numbers - About + जानकारी संस्करण - Developer + विकासक श्रोत कोड बदलाव संपर्क लाइसेंस - Support development, unlock everything + कॉपीराइट + विकास का समर्थन करें, सब कुछ अनलॉक करें You can save a starving developer for just %s Lifetime upgrade for %1$s %2$s @@ -271,68 +304,73 @@ Unlock + donate for %1$s %2$s Thank you for supporting QKSMS! You now have access to all QKSMS+ features - QKSMS+ is free for F-Droid users! If you\'d like to support development, a donation would be highly appreciated. - Donate via PayPal + एक त्रूटि हुई: कृपया फिर से कोशिश करें + QKSMS+ F-Droid उपयोगकर्ताओं के लिए निःशुल्क है! यदि आप विकास का समर्थन करना चाहते हैं, तो दान की अत्यधिक सराहना की जाएगी। + पेपैल के माध्यम से दान करें जल्द आ रहा है - Premium themes - Unlock beautiful theme colors not available on the Material Design palette - Custom auto-emoji - Create custom auto-emoji shortcuts - Message backup - Automatically back up your messages. Never again worry about losing your history if you change phones or your phone gets lost - Scheduled messages - Schedule messages to automatically be sent at a specific time and date + प्रीमियम थीम + मटीरियल डिज़ाइन पैलेट पर उपलब्ध नहीं होने वाले सुंदर थीम रंगों को अनलॉक करें + कस्टम ऑटो-इमोजी + कस्टम ऑटो-इमोजी शॉर्टकट बनाएं + संदेश बैकअप + अपने संदेशों का स्वचालित रूप से बैकअप लें। यदि आप फ़ोन बदलते हैं या आपका फ़ोन खो जाता है, तो अपना इतिहास खोने के बारे में फिर कभी चिंता न करें + अनुसूचित संदेश + संदेशों को एक विशिष्ट समय और तिथि पर स्वचालित रूप से भेजे जाने के लिए अनुसूचित करें Delayed sending - Wait a few seconds before sending your message - Automatic night mode - Enable night mode based on the time of day - Advanced blocking - Block messages that contain keywords or match patterns - Auto-forward - Automatically forward messages from certain senders - Auto-respond - Automatically respond to incoming messages with a preset response + अपना संदेश भेजने से पहले कुछ सेकंड प्रतीक्षा करें + स्वचालित रात मोड + दिन के समय के आधार पर रात्रि मोड सक्षम करें + उन्नत अवरोधन + कीवर्ड या मिलान पैटर्न वाले संदेशों को ब्लॉक करें + स्व-फ़ॉरवर्ड + कुछ प्रेषकों के संदेशों को स्वचालित रूप से अग्रेषित करें + स्व-प्रतिक्रिया + पूर्व निर्धारित प्रतिक्रिया के साथ आने वाले संदेशों का स्वचालित रूप से जवाब दें अधिक - QKSMS is under active development, and your purchase will include all future QKSMS+ features! + QKSMS सक्रिय विकास के अधीन है, और आपकी खरीदारी में भविष्य की सभी QKSMS+ सुविधाएँ शामिल होंगी! तैयार हो रहा है… अधिक वार्तालाप देखें - Mark as read + पढ़ा हुआ चिह्नित करें कॉल मिटायें अधिक दिखाएं कम दिखाएं वार्तालाप खोलें + सामग्री + हेक्स रंग + लागू करें - None - Archive - Delete - Block - Call - Mark read - Reply + कोई नहीं + संग्रह + मिटायें + अवरुदध करें + कॉल + पढ़ा हुआ चिह्नित करें + जवाब दे - Yes - Continue - Cancel - Delete - Save - Stop - More - Set - Undo - Copied - Archived conversation + हाँ + जारी रखें + रद्द करें + मिटायें + सहेजें + बंद करें + अधिक + सेट करें + पूर्ववत करें + प्रतिलिपि बनाई गई हैं। + संग्रहीत बातचीत + इसका उपयोग करने के लिए आपको QKSMS+ को अनलॉक करना होगा - New message - %s new messages + नई संदेश + %s नए संदेश संदेश नही भेजा गया %s को संदेश भेजने में असफल - System - Disabled - Always on - Automatic + प्रणाली + अक्षम करें + हमेशा चालू + स्वचालित नाम व संदेश दिखाएं @@ -347,32 +385,32 @@ कोइ विलम्ब नही - Short - मध्यम - बड़ा + 3 सेकंड + 5 सेकंड + 10 सेकंड - Automatic - 100KB - 200KB - 300KB - 600KB - 1000KB - 2000KB - No compression + स्वचालित + 100केबी + 200केबी + 300केबी + 600केबी + 1000केबी + 2000केबी + कोई संपीड़न नहीं ठीक एक क्षण दें - On my way + रास्ते में हूं शुक्रिया सही है नया क्या है - Agreed + सहमत हूँ नहीं - Love you + सप्रेम मुझे खेद है - LOL + लोल ठीक है diff --git a/presentation/src/main/res/values-hr/strings.xml b/presentation/src/main/res/values-hr/strings.xml index 227c93b45b780766511e6e199380d83bfa555755..defb28ed18cf4857f9943f2d6d6c02ee9ea6d680 100644 --- a/presentation/src/main/res/values-hr/strings.xml +++ b/presentation/src/main/res/values-hr/strings.xml @@ -18,286 +18,298 @@ ~ along with QKSMS. If not, see . --> - New conversation - Compose - Shortcut disabled + Novi razgovor + Sastavi + Prečac onemogućen Arhivirano Postavke Obavijesti + Tema Pretraži poruke… Unesite ime ili broj Preskoči Nastavi - Add person + Dodaj osobu Nazovi Detalji - Save to gallery - Share - Open navigation drawer + Spremi u galeriju + Podijeli + Otvori navigacijsku ladicu %d odabrano Očisti Arhiviraj Dearhiviraj Izbriši - Add to contacts - Pin to top - Unpin - Mark read - Mark unread + Dodaj kontaktima + Prikvači na vrh + Otkvači + Označi kao pročitano + Označi kao nepročitano Blokiraj - Syncing messages… + Sinkronizacija poruka… Vi: %s - Draft - Results in messages - %d messages - Vaši razgovori će se pojaviti ovdje + Skica + Rezultati u porukama + %d poruka + Vaši razgovori pojavit će se ovdje Nema rezultata Vaši arhivirani razgovori će se pojaviti ovdje Započni novi razgovor - Love texting again - Make Message your default SMS app - Change - Permission required - Message needs permission to send and view SMS messages - Message needs permission to view your contacts - Allow + Ponovno zavolite poruke + Postavite QKSMS kao zadanu aplikaciju za SMS-ove + Promijeni + Potrebne su dozvole + QKSMS treba dozvolu za slanje i pregledavanje SMS poruka + QKSMS treba dozvolu za pregledavanje vaših kontakata + QKSMS needs permission to display notifications + Dopusti Poruke Arhivirano Zakazano - Blocking + Blokiranje  Više Postavke Pomoć i povratne informacije - Invite friends + Pozovi prijatelje + Otključajte čudesne nove značajke i podržite razvoj + Uživate u QKSMS? + Podijelite malo ljubavi i ocijenite nas na Google Playu! + U REDU! + ODBACI Izbriši - Are you sure you would like to delete this conversation? - Are you sure you would like to delete %d conversations? - Are you sure you would like to delete %d conversations? + Sigurno želite izbrisati ovaj razgovor? + Sigurno želite izbrisati %d razgovora? + Sigurno želite izbrisati %d razgovora? Kopiraj tekst Proslijedi Izbriši - Choose a phone number - %s ∙ Default - Just once - Always + Odaberite telefonski broj + %s ∙ zadano + Samo jednom + Uvijek %d odabrano - %1$d of %2$d results - Send as group message - Recipients and replies will be visible to everyone + Rezultat %1$d od %2$d + Pošalji kao grupnu poruku + Primatelji i odgovori bit će vidljivi svima Ovo je početak vašeg razgovora. Recite nešto lijepo! - Contact card - Scheduled for - Selected time must be in the future! - Added to scheduled messages + Kartica kontakta + Zakazano za + Odabrano vrijeme mora biti u budućnosti! + Morate otključati QKSMS+ za zakazivanje poruke + Dodano u zakazane poruke Napiši poruku… Kopiraj tekst Proslijedi Izbriši - Previous - Next - Clear - Message details - Type: %s - From: %s - To: %s - Subject: %s - Priority: %s - Size: %s - Sent: %s - Received: %s - Delivered: %s - Error code: %d + Prethodno + Sljedeće + Očisti + Detalji poruke + Vrsta: %s + Od: %s + Za: %s + Predmet: %s + Prioritet: %s + Veličina: %s + Poslano: %s + Primljeno: %s + Dostavljeno: %s + Kod greške: %d Dodaj privitak Priloži fotografiju - Uslikaj fotografiju - Schedule message - Attach a contact - Error reading contact + Snimi fotografiju + Zakaži poruku + Priloži kontakt + Greška kod čitanja kontakta - SIM %1$d (%2$s) selected - %s selected, change SIM card + SIM %1$d (%2$s) odabran + %s odabrano, promijeni SIM karticu Pošalji poruku Slanje… Isporučeno %s Slanje nije uspjelo. Dodirnite da biste pokušali ponovno Detalji - Address copied - Conversation title + Adresa kopirana + Naslov razgovora Obavijesti - Arhiva + Tema + Arhiviraj Dearhiviraj Blokiraj Deblokiraj Izbriši razgovor - Couldn\'t load media - Saved to gallery - Backup and restore - Backing up messages - Restoring from backup - Last backup - Loading… - Never - Restore - Select a backup - Backup in progress… - Restore in progress… - Restore from backup - Are you sure you would like to restore your messages from this backup? - Stop restore - Messages that have already been restored will remain on your device - Backups - No backups found - - %d message - %d messages - %d messages - - Currently, only SMS is supported by Backup and Restore. MMS support and scheduled backups will be coming soon! - Backup now - Parsing backup… - %d/%d messages - Saving backup… - Syncing messages… - Finished! - Backup and restore - Scheduled - Automatically send a message, at the exact moment you\'d like - Hey! When was your birthday again? - It\'s on December 23rd - Happy birthday! Look at what a great friend I am, remembering your birthday + Nije moguće učitati medijske datoteke + Spremljeno u galeriju + Sigurnosno kopiranje i vraćanje + Sigurnosno kopiranje poruka + Vraćanje podataka iz sig. kopije + Učitavanje… + Nikad + Backup location + Set folder + Vraćanje + Odaberite sig. kopiju + Otključajte QKSMS+ za korištenje sig. kopiranja i vraćanja podataka + Sigurno kopiranje u tijeku… + Vraćanje podataka u tijeku… + Vrati iz sigurnosne kopije + Zaustavi vraćanje + Poruke koje su već vraćene ostat će na vašem uređaju + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details + Sigurnosne kopije + Nisu pronađene sigurnosne kopije + Trenutno je samo SMS podržan u sigurnosnom kopiranju i vraćanju. Podrška za MMS i zakazane sigurnosne kopije dolazi uskoro! + Sig. kopiraj sada + Analiziranje sig. kopije… + %d/%d poruka + Spremanje sigurnosne kopije… + Sinkronizacija poruka… + Dovršeno! + Sig. kopiranje i vraćanje + Zakazano + Automatski šaljite poruku u točno određeno vrijeme + Bok! Kad ti je bio rođendan? + 23. prosinca + Sretan rođendan! Vidi kako sam dobra prijateljica, zapamtila tvoj rođendan - Sending on December 23rd  - Schedule a message - Scheduled message + Slanje 23. prosinca + Zakaži poruku + Zakazana poruka - Send now - Copy text - Delete + Pošalji sada + Kopiraj tekst + Izbriši Izgled Općenito QK odgovor + Tema Noćni način Potpuno crni noćni način Vrijeme početka Vrijeme završetka - Automatic contact colors + Automatske boje kontakata Veličina fonta - Koristi sustavski font - Automatsk emoji + Koristi font sustava + Automatski emoji Obavijesti - Tap to customize - Actions - Button 1 - Button 2 - Button 3 + Dodirnite za prilagođavanje + Radnje + Tipka 1 + Tipka 2 + Tipka 3 Pregledi obavijesti - Wake screen + Uključi zaslon Vibracija Zvuk - None + Nema QK odgovor Skočni prozor za nove poruke Dodirnite za odbacivanje Dodirnite izvan skočnog prozora za zatvaranje - Delayed sending - Swipe actions - Configure swipe actions for conversations - Right swipe - Left swipe - CHANGE + Odgođeno slanje + Radnje poteza + Konfigurirajte radnje poteza za razgovore + Desni potez + Lijevi potez + PROMIJENI - None - Archive - Delete - Block - Call - Mark read - Mark unread + Nema + Arhiviraj + Izbriši + Blokiraj + Nazovi + Označi kao pročitano + Označi kao nepročitano Potvrde o dostavi Budite sigurni da su se poruke uspješno poslale - Signature - Add a signature to the end of your messages - Strip naglasci + Potpis + Dodajte potpis na kraj vaših poruka + Uklanjanje naglasaka Uklonite naglaske sa znakova u odlaznim SMS porukama - Mobile numbers only - When composing a message, only show mobile numbers - Delete old messages automatically - Messages will be deleted after the specified number of days - Number of days - Never - Delete old messages automatically? - If you proceed, %1$d messages will be deleted now + Samo mobilni brojevi + Kod sastavljanja poruke, prikaži samo mobilne brojeve + Izbriši stare poruke automatski + Poruke bit će izbrisane nakon odabranog broja dana + Broj dana + Nikad + Brisati stare poruke automatski? + Ako nastavite, sada će biti izbrisan sljedeći broj poruka: %1$d - After 1 day - After %d days - After %d days + Nakon 1 dana + Nakon %d dana + Nakon %d dana - Send long messages as MMS - If your longer text messages are failing to send, or sending in the wrong order, you can send them as MMS messages instead. Additional charges may apply - Auto-compress MMS attachments + Šalji duge poruke kao MMS + Ako imate probleme sa slanjem dužih poruka ili ako se šalju krivim redoslijedom, možete ih poslati kao MMS poruke. Možda će doći do dodatnih troškova + Automatski kompresiraj MMS priloge Uskladi poruke - Ponovno uskladite svoje poruke sa nativnom Android SMS bazom podataka - O aplikaciji Message + Ponovno uskladite svoje poruke s Androidovom nativnom bazom SMS-ova + O QKSMS-u Verzija %s - Debug logging enabled - Debug logging disabled - Enter duration (seconds) - Blocking - Drop messages - Drop incoming messages from blocked senders instead of hiding them - Blocked conversations - Blocking Manager + Omogućen zapisnik za ispravljanje grešaka + Onemogućen zapisnik za ispravljanje grešaka + Unesite trajanje (sekunde) + Blokiranje + Odbaci poruke + Odbacite dolazne poruke od blokiranih pošiljatelja umjesto da ih samo sakrivate + Blokirani razgovori + Upravitelj za blokiranje QKSMS - Built-in blocking functionality in QKSMS - Block spam messages, numbers & unknown calls with blacklist & Schedule - Automatically filter your calls and messages in one convenient place! Community IQ™ allows you to prevent unwanted messages from community known spammers - Automatically filter messages from unsolicited numbers by using the \"Should I Answer\" app - Copy blocked numbers - Continue to %s and copy over your existing blocked numbers - Blocked numbers - Your blocked numbers will appear here - Block a new number - Block texts from - Phone number - Block - Blocked messages - Your blocked messages will appear here - Block - Unblock + Ugrađena funkcionalnost blokiranja u QKSMS-u + Blokirajte neželjene poruke, brojeve i nepoznate pozive pomoću crne liste i zakazivanja + Automatski filtrirajte svoje pozive i poruke na jednom mjestu! Community IQ™ omogućuje vam filtriranje neželjenih poruka od spammera poznatih zajednici + Automatski filtrirajte poruke od neželjenih brojeva pomoću aplikacije \"Should I Answer\" + Kopiraj blokirane brojeve + Nastavite na %s i kopirajte svoje postojeće blokirane brojeve + Blokirani brojevi + Vaši blokirani brojevi pojavit će se ovdje + Blokiraj novi broj + Blokiraj poruke od + Telefonski broj + Blokiraj + Blokirane poruke + Vaše blokirane poruke pojavit će se ovdje + Blokiraj + Odblokiraj - Continue to %s and block this number - Continue to %s and block these numbers - Continue to %s and block these numbers + Nastavi na %s i blokiraj ovaj broj + Nastavi na %s i blokiraj ove brojeve + Nastavi na %s i blokiraj ove brojeve - Continue to %s and allow this number - Continue to %s and allow these numbers - Continue to %s and allow these numbers + Nastavi na %s i dopusti ovaj broj + Nastavi na %s i dopusti ove brojeve + Nastavi na %s i dopusti ove brojeve O aplikaciji Verzija - Autor + Razvijatelj Izvorni kod Popis promjena Kontakt - Licenca + Licencija Autorska prava Podržite razvoj, otključajte sve Možete spasiti izgladnjelog programera za samo %s Doživotna nadogradnja za %1$s %2$s - Otključajte + za %1$s %2$s + Otključajte + donirajte za %1$s %2$s Hvala vam za podržavanje QKSMS! Sada imate pristup svim QKSMS+ značajkama - An error has occurred, please try again - QKSMS+ is free for F-Droid users! If you\'d like to support development, a donation would be highly appreciated. + Dogodila se greška, pokušajte ponovno + QKSMS+ ke besplatan za korisnike F-Droida! Ako želite podržati razvoj, vrlo smo zahvalni na donacijama. Donirajte putem PayPala Uskoro dolazi Premium teme @@ -307,7 +319,7 @@ Sigurnosno kopiranje poruka Automatski sigurnosno kopirajte svoje poruke. Nikad više nemojte brinuti zbog gubitka povijesti ako promijenite telefon ili ga izgubite Zakazane poruke - Schedule messages to automatically be sent at a specific time and date + Zakažite poruke za automatsko slanje u specificirano vrijeme Odgođeno slanje Pričekajte nekoliko sekundi prije slanja poruke Automatski noćni način @@ -319,87 +331,91 @@ Automatsko odgovaranje Automatski odgovorite na poruke sa prilagođenim odgovorima  Više - QKSMS is under active development, and your purchase will include all future QKSMS+ features! + QKSMS aktivno se razvija i vaša kupnja sadržat će sve buduće QKSMS+ značajke! Učitavanje… - View more conversations - Mark read - Call - Delete - Show more - Show less - Open conversation + Prikaži više razgovora + Označi kao pročitano + Nazovi + Izbriši + Prikaži više + Prikaži manje + Otvori razgovor + Materijalna + HEX + Primijeni - None - Archive - Delete - Block - Call - Mark read - Reply + Nema + Arhiviraj + Izbriši + Blokiraj + Nazovi + Označi kao pročitano + Odgovori - Yes - Continue + Da + Nastavi Odustani Izbriši - Save - Stop + Spremi + Zaustavi  Više - Set + Postavi Poništi Kopirano Razgovor je arhiviran + Morate otključati QKSMS+ za korištenje ovog - New message - %s new messages - %s new messages + Nova poruka + %s nove poruke + %s novih poruka Poruka nije poslana - Poruku %s se nije uspjela poslati + Poruka za %s nije se uspjela poslati - System - Disabled - Always on - Automatic + Sustav + Onemogućeno + Uvijek uključeno + Automatski - Show name and message - Show name - Hide contents + Prikaži ime i poruku + Prikaži ime + Sakrij sadržaj - Small - Normal - Large - Larger + Malo + Normalno + Veliko + Veće - No delay - 3 seconds - 5 seconds - 10 seconds + Bez odgode + 3 sekunde + 5 sekundi + 10 sekundi - Automatic + Automatski 100KB 200KB 300KB 600KB 1000KB 2000KB - No compression + Bez kompresije - Okay - Give me a moment - On my way - Thanks - Sounds good - What\'s up? - Agreed - No - Love you - Sorry + U redu + Samo trenutak + Na putu sam + Hvala + Zvuči dobro + Što ima? + Slažem se + Ne + Volim te + Oprosti LOL - That\'s okay + U redu je diff --git a/presentation/src/main/res/values-hu/strings.xml b/presentation/src/main/res/values-hu/strings.xml index a1e790b9982bb2098628bbb2565e515f86a3a756..6fafb51b58f94c86124a7e13276d6b5679cb1c30 100644 --- a/presentation/src/main/res/values-hu/strings.xml +++ b/presentation/src/main/res/values-hu/strings.xml @@ -24,6 +24,7 @@ Archivált Beállítások Értesítések + Téma Keresés az üzenetek között… Adj meg egy nevet vagy telefonszámot Kihagy @@ -42,8 +43,8 @@ Hozzáadás az ismerősökhöz Rögzítés a tetejére Rögzítés törlése - Mark read - Mark unread + Megjelölés olvasottként + Megjelölés olvasatlanként Tiltás Üzenetek szinkronizálása… Te: %s @@ -55,13 +56,12 @@ Az archivált beszélgetéseid itt jelennek meg Új beszélgetés kezdeményezése Szeresd újból az SMS-ezést - A Message beállítása alapértelmezett SMS - alkalmazásként - + A QKSMS beállítása alapértelmezett SMS alkalmazásként Módosít Engedély szükséges A QKSMS-nek engedélyt kell kapnia az SMS üzenetek küldésére és megtekintésére A QKSMS-nek engedélyt kell kapnia a telefonkönyv megtekintésére + QKSMS needs permission to display notifications Engedélyez Bejövő üzenetek Archivált @@ -71,6 +71,11 @@ Beállítások Súgó és visszajelzés Ismerősök meghívása + Juss érdekes, új lehetőségekhez és támogasd fejlesztést + Tetszik a QKSMS? + Oszd meg a szeretetet és értékelj minket a Google Playen! + OKÉ! + MELLŐZÉS Törlés Biztos, hogy törölni szeretnéd ezt a beszélgetést? @@ -93,6 +98,7 @@ Névjegy Várakozik A kiválasztott időpontnak a jövőben kell lennie! + Aktiválnod kell a QKSMS+-t hogy időzített üzeneteteket tudj használni Hozzáadva az időzített üzenetekhez Írj egy üzenetet… Szöveg másolás @@ -119,7 +125,7 @@ Személy hozzáadása Hiba a személy olvasása közben - SIM %1$d (%2$s) selected + SIM %1$d (%2$s) kiválasztva %s kiválasztva, cserélj SIM kártyát Üzenet küldése Küldés… @@ -129,6 +135,7 @@ Cím átmásolva A beszélgetés témája Értesítések + Téma Archivál Archiválás visszavonása Blokkolás @@ -139,24 +146,26 @@ Mentés és visszaállítás Üzenetek mentése Üzenetek visszaállítása mentésből - Utolsó mentés Betöltés… Soha + Backup location + Set folder Visszaállítás Válassz egy mentést Oldd fel a QKSMS+-t a mentés és visszaállítás használatához Mentés folyamatban… Visszaállítás folyamatban… Visszaállítás mentésből - Biztos vagy benne hogy vissza akarod állítani a mentésből a üzeneteket? Visszaállítás megállítása A már visszaállított üzenetek a készülékeden maradnak + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details Mentések Nincsenek mentések - - %d üzenet - %d üzenet - Jelenleg a mentés csak az SMS üzeneteket menti. Az MMS támogatás és az időzített mentések hamarosan jönnek! Mentés most Mentés elemzése… @@ -182,6 +191,7 @@ Megjelenés Általános QK válasz + Téma Éjszakai mód Éjfekete mód Kezdés ideje @@ -215,10 +225,10 @@ Nincs Archiválás Törlés - Block - Call - Mark read - Mark unread + Blokkolás + Hívás + Megjelölés olvasottként + Megjelölés olvasatlanként Elküldés megerősítése Megerősíti, hogy az üzenetek sikeresen el lettek-e küldve @@ -228,15 +238,15 @@ A kimenő SMS-üzenetek ékezetes karaktereinek átalakítása Csak mobilszámok Üzenet írásánál csak a mobilszámokat mutassa - Delete old messages automatically - Messages will be deleted after the specified number of days - Number of days - Never - Delete old messages automatically? - If you proceed, %1$d messages will be deleted now + Régi üzenetek automatikus törlése + Az üzenetek törlődnek pár nap múlva + Napok száma + Soha + Szeretné törölni a régi üzeneteket automatikusan? + Ha folytatod, %1$d üzenet törlődik - After 1 day - After %d days + 1 nap múlva + %d nap múlva A hosszú üzenetek MMS-ként küldése Ha a hosszabb üzenetek küldése sikertelen, vagy rossz sorrendben érkeznek akkor lehet őket MMS-ként küldeni, de ez díjköteles lehet @@ -255,7 +265,7 @@ Tiltáskezelő QKSMS A QKSMS beépített tiltási funkciója - Block spam messages, numbers & unknown calls with blacklist & Schedule + Spam üzenetek blokkolása, számok & ismeretlek hívások feketelistával & Ütemezés Egy kényelmesen kezelhető helyen a hívások és üzenetek szűrése! A Community IQ™ megakadályozza a közösség által ismert spammerek üzeneteit Automatikusan szűrheti az üzeneteket a nem kívánt számok alapján a \"Should I Answer\" alkalmazás használatával Tiltott számok másolása @@ -285,6 +295,7 @@ Változások listája Kapcsolat Licensz + Copyright Fejlesztés támogatása, minden funkció engedélyezése Csak %s hogy megmenthess egy éhező fejlesztőt @@ -293,7 +304,7 @@ Minden funkció engedélyezése + adomány %1$s %2$s Köszönjük, hogy támogatot a QKSMS-t! MOst hozzáférsz minden QKSMS+ funkcióhoz - An error has occurred, please try again + Hiba történt, kérjük próbáld újra A QKSMS+ minden F-Droid felhasználónak ingyenes. Ha támogatni szeretnéd a fejlesztést az alábbi módon megteheted. Támogatás PayPalon keresztül Hamarosan @@ -319,20 +330,23 @@ A QKSMS folyamatos fejlesztés alatt áll és a vásárlásod a jövőbeni QKSMS+ funkciókat is tartalmazza! Betöltés… További társalgások megtekintése - Mark read + Megjelölés olvasottként Hívás Törlés Több megjelenítése Kevesebb megjelenítése Társalgás kinyitása + Material + HEX + Alkalmaz Nincs - Archive - Delete - Block - Call - Mark read - Reply + Arhiválás + Törlés + Blokkolás + Hívás + Megjelölés olvasottként + Válasz Igen Folytatás @@ -371,19 +385,19 @@ Nincs késleltetés - 3 seconds - 5 seconds - 10 seconds + 3 másodperc + 5 másodperc + 10 másodperc - Automatic - 100KB + Automatikus + 100 KB 200KB 300KB 600KB 1000KB 2000KB - No compression + Nincs tömörítés Oké diff --git a/presentation/src/main/res/values-in/strings.xml b/presentation/src/main/res/values-in/strings.xml index 6ac086a877de534da0a00cc82f9b38a103587715..b6565b36da31359271aa805f73318b8da8113e16 100644 --- a/presentation/src/main/res/values-in/strings.xml +++ b/presentation/src/main/res/values-in/strings.xml @@ -24,6 +24,7 @@ Diarsipkan Setelan Notifikasi + Tema Cari kotak masuk… Ketik nama atau nomor Lewati @@ -58,10 +59,9 @@ Tetapkan QKSMS sebagai aplikasi SMS default anda Ubah Membutuhkan izin - Message membutuhkan izin untuk mengirim dan membaca pesan - SMS - - Message membutuhkan izin untuk membaca kontak anda + QKSMS membutuhkan izin untuk mengirim dan membaca pesan SMS + QKSMS membutuhkan izin untuk membaca kontak anda + QKSMS needs permission to display notifications Izinkan Kotak masuk Diarsipkan @@ -71,6 +71,11 @@ Setelan Bantuan & umpanbalik Undang teman + Buka fitur-fitur baru yang menakjubkan, dan dukung pengembangan + Menikmati QKSMS? + Share some love and rate us on Google Play! + OKE! + ABAIKAN Hapus Apakah anda yakin ingin menghapus percakapan ini? @@ -92,6 +97,7 @@ Kartu nama Jadwalkan pada Waktu yang dipilih harus berada di masa depan! + Anda harus membuka akses QKSMS+ untuk menggunakan pesan terjadwal Ditambahkan ke pesan terjadwal Tulis pesan… Salin teks @@ -128,6 +134,7 @@ Alamat disalin Judul percakapan Notifikasi + Tema Arsip Batalkan arsip Blokir @@ -138,23 +145,26 @@ Cadangan dan pemulihan Mencadangankan pesan Memulihkan cadangan pesan - Cadangan terakhir Memuat… Tidak pernah + Backup location + Set folder Pulihkan Pilih cadangan Silakan buka akses QKSMS+ untuk menggunakan fitur cadangan dan pemulihan Pencadangan sedang berlangsung… Pemulihan sedang berlangsung… Pulihkan dari cadangan - Apakah anda yakin ingin memulihkan pesan anda dari cadangan ini? Setop pemulihan Pesan yang telah dipulihkan akan tetap berada di perangkat anda + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details Cadangan Cadangan tidak ditemukan - - %d pesan - Saat ini, Cadangan dan Pemulihan hanya mendukung pesan SMS. Dukungan MMS dan cadangan terjadwal akan segera datang! Cadangkan sekarang Membaca cadangan… @@ -180,6 +190,7 @@ Tampilan Umum Balasan cepat + Tema Mode malam Mode malam hitam pekat Waktu mulai @@ -252,7 +263,7 @@ Pengelola Pemblokiran QKSMS Fitur pemblokiran pesan di dalam QKSMS - Block spam messages, numbers & unknown calls with blacklist & Schedule + Blokir pesan spam, nomor & panggilan tak dikenal dengan daftar hitam & Jadwal Otomatis menyaring panggilan dan pesan di dalam satu tempat! Community IQ™ memungkinkan anda memblokir pesan yang tidak diinginkan dari daftar spammer Secara otomatis menyaring pesan dari nomor yang tidak diinginkan menggunakan aplikasi \"Should I Answer\" Salin nomor yang diblokir @@ -289,7 +300,7 @@ Unlock + donate for %1$s %2$s Terima kasih telah mendukung QKSMS! Anda sekarang bisa mengakses semua fitur QKSMS+ - An error has occurred, please try again + Telah terjadi kesalahan, silakan coba kembali QKSMS+ selalu gratis untuk pengguna F-Droid! Jika anda ingin mendukung pengembangan, jangan ragu untuk donasi. Donasi via PayPal Segera hadir @@ -321,6 +332,9 @@ Tampilkan lainnya Tampilkan sedikit Buka percakapan + Material + HEX + Terapkan Tidak ada Arsip @@ -341,6 +355,7 @@ Urungkan Disalin Percakapan diarsipkan + Anda harus membuka akses QKSMS+ untuk menggunakan ini %s pesan baru diff --git a/presentation/src/main/res/values-is/e_strings.xml b/presentation/src/main/res/values-is/e_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..db278ae5afbf1b4cafc70018826f7d7bd5f7077f --- /dev/null +++ b/presentation/src/main/res/values-is/e_strings.xml @@ -0,0 +1,34 @@ + + + + Skilaboð + Gerðu Skilaboð/Message að sjálfgefnu SMS-forriti + Skilaboðaforritið þarf heimild til að senda og skoða SMS-skilaboð + Skilaboðaforritið þarf heimild til að skoða tengiliðina þína + Um Message-forritið + Skilaboð + Innbyggð virkni útilokana í Skilaboð/Message + Message-kóðanum er kvíslað frá QKSMS + Upplýsingar skilaboða + Útgáfa forrits + -Message/Skilaboð er SMS-skilaboðaforrit með opinn grunnkóða sem kemur í staðinn fyrir staðalforritið í Android. + Meðferð persónuupplýsinga + Þjónustuskilmálar + Höfundar + Get ekki bætt við auðu símanúmeri. Endilega reyndu aftur + Get ekki bætt við auðum skilaboðum. Endilega reyndu aftur + \ No newline at end of file diff --git a/presentation/src/main/res/values-is/strings.xml b/presentation/src/main/res/values-is/strings.xml deleted file mode 100644 index 8ff52b2cbeaf90f7ba7e9d22a41c2aa9dfcbdcbe..0000000000000000000000000000000000000000 --- a/presentation/src/main/res/values-is/strings.xml +++ /dev/null @@ -1,326 +0,0 @@ - - - Í safni - Áætlað - Meira - Stillingar - Hjálp og ábendingar - Eyða - Alltaf - %d valið - Skrifaðu skilaboð… - Afrita texta - Áfram - Eyða - Fyrri - Næstu - Hreinsa - Í LAGI! - %s ∙ Sjálfgefið - Skilaboð - Nýtt spjall - Semja skilaboð - Í safni - Stillingar - Tilkynningar - Þema - Sleppa - Halda áfram - Símtal - Nánar - Deila - Opna yfirlitsskúffu - %d valið - Hreinsa - Safn - Taka úr safni - Eyða - Bæta við tengiliði - Losa - Merkja sem lesið - Merkja sem ólesið - Útiloka - Þú: %s - Drög - Samtölin þín birtast hér - Engar niðurstöður - Breyta - Krafist er heimildar - Leyfa - Innhólf - Nánar um skilaboð - Tegund: %s - Frá: %s - Til: %s - Efni: %s - Forgangur: %s - Stærð: %s - Tók við: %s - Senda skilaboð - Vistfang afritað - Tilkynningar - Taka úr safni - Eyða samtali - Síðasta öryggisafrit - Aldrei - Endurheimta úr öryggisafriti - - %d skilaboð - %d skilaboð - - Lokið! - Hreinn svartur næturhamur - Tilkynningar - Aðgerðir - Titringur - Hljóð - Strjúka til hægri - Strjúka til vinstri - Fjöldi daga - Aldrei - - Eftir 1 dag - Eftir %d daga - - Útgáfa %s - Símanúmer - Upprunakóði - Notkunarleyfi - Höfundarréttur - Forritari - Breytingaskrá - Tengiliður - Útgáfa forrits - Meðferð persónuupplýsinga - Þjónustuskilmálar - Styrkja með PayPal - Merkja sem lesið - Sýna meira - Material - Afritað - - Ný skilaboð - %s ný skilaboð - - Höfundar - AFGREIÐA - Sent: %s - Afhent: %s - Villukóði: %d - Bæta við viðhengi - Hengja við mynd - Taka ljósmynd - Setja skilaboð á áætlun - Hengja við tengilið - Villa við að lesa tengilið - SIM %1$d (%2$s) valið - %s valið, skipta um SIM-kort - Sendi… - Afhenti %s - Mistókst að senda. Ýttu til að reyna aftur - Nánar - Þema - Safn - Útiloka - Öryggisafrit - Taka öryggisafrit núna - %d/%d skilaboð - Vista öryggisafrit… - Samstilli skilaboð… - Afritun og endurheimting - Áætlað - Þema - Strokaðgerðir - BREYTA - Undirskrift - Samstilla skilaboð - Um Message-forritið - Skilaboð - Útilokuð númer - Útiloka - Útiloka - Aflétta útilokun - Um hugbúnaðinn - Útgáfa - Kemur bráðum - Meira - Hleður… - Símtal - Eyða - Sýna minna - HEX - Aflétta útilokun - Hleður… - Endurheimta - Setja skilaboð á áætlun - Áætluð skilaboð - Útlit - Almennt - Næturhamur - Upphafstími - Lokatími - Leturstærð - Ýttu til að sérsníða - Hnappur 1 - Hnappur 2 - Hnappur 3 - Ekkert - Virkja - - Halda áfram - Hætta við - Eyða - Vista - Stöðva - Meira - Setja - Afturkalla - Samtal í safni - Skilaboð ekki send - Mistókst að senda skilaboð til %s - Flýtileið er óvirk - Leita í innhólfi… - Settu inn nafn eða símanúmer - Bæta við persónu - Vista í myndasafn - Festa efst - Samstilli skilaboð… - Niðurstöður í skilaboðum - %d skilaboð - Samtölin sem þú hefur sett í safn birtast hér - Byrja nýtt samtal - Aflæstu QKSMS+ til að nota öryggisafritun og endurheimtu - Öryggisafritun í gangi… - Endurheimt í gangi… - Stöðva endurheimt - Engin öryggisafrit fundust - Þátta öryggisafrit… - Sjálfvirk litun tengiliða - Nota kerfisletur - Útilokun - Útilokuð skilaboð - Message-kóðanum er kvíslað frá QKSMS - Sjálfvirk svörun - Skoða fleiri samtöl - Opna samtal - Þú verður að aflæsa QKSMS+ til að nota þetta - Skilaboðaforritið þarf heimild til að senda og skoða SMS-skilaboð - Skilaboðaforritið þarf heimild til að skoða tengiliðina þína - - Ertu viss um að þú viljir eyða þessu samtali\? - Ertu viss um að þú viljir eyða %d samtölum\? - - Senda sem hópskilaboð - Bætt í áætluð skilaboð - Titill samtals - Vistað í myndasafn - Afritun og endurheimting - Öryggisafrita skilaboð - Endurheimti úr öryggisafriti - Veldu öryggisafrit - Sjálfvirk tjáningartákn - Forskoðun tilkynninga - Tafin sending - Staðfestingar á afhendingu - Senda langa texta sem MMS - Afrita útilokuð númer - Útilokuðu skilaboðin þín birtast hér - Upplýsingar skilaboða - Gaman aftur að senda SMS - Gerðu Skilaboð/Message að sjálfgefnu SMS-forriti - Veldu símanúmer - Bara einu sinni - %1$d af %2$d niðurstöðum - Áætlað - Valinn tími verður að vera í framtíðinni! - Þú verður að aflæsa QKSMS+ til að áætlaða sendingu skilaboða - Vekja skjáinn - Ýttu utan við gluggann til að loka honum - Stilla strokuaðgerðir vegna samtala - Staðfesta að tekist hafi að senda skilaboð - Bæta undirskrift við enda skilaboðanna þinna - Einungis farsímanúmer - Eyða gömlum skilaboðum sjálfkrafa - Eyða gömlum skilaboðum sjálfkrafa\? - Útilokuðu símanúmerin þín birtast hér - Útiloka nýtt símanúmer - Útiloka textaskilaboð frá - Styðja við áframhaldandi þróun, aflæsa öllu - Villa kom upp, endilega reyndu aftur - Sérsniðin sjálfvirk tjáningartákn - Sjálfvirkur næturhamur - Virkja næturham eftir tíma dagsins - Ítarlegri útilokun - Sjálfvirk áframsending - Aflæstu frábærum eiginleikum og styddu við áframhaldandi þróun - Útilokun - Bjóddu vinum - Gat ekki hlaðið inn myndefni - Sprettgluggi fyrir ný skilaboð - Ýttu til að afgreiða - Ef þú heldur áfram verður %1$d skilaboðum eytt - Þjappa sjálfvirkt MMS-viðhengjum - Atvikaskrá villukembingar virk - Atvikaskrá villukembingar óvirk - Settu inn tímalengd (sekúndur) - Henda skilaboðum - Henda innkomnum skilaboðum frá útilokuðum sendendum í stað þess að fela þau - Útilokuð samtöl - Umsýsla útilokana - Öryggisafrit skilaboða - Áætluð skilaboð - Tafin sending - Kanntu vel við Skilaboð/Message\? - Deildu reynslu þinni og gefðu okkur einkunn á Google Play! - Get ekki bætt við auðu símanúmeri. Endilega reyndu aftur - Get ekki bætt við auðum skilaboðum. Endilega reyndu aftur - Nafnspjald - Fjarlægja áherslumerki - Fjarlægja áherslumerki af stöfum í útsendum SMS-skilaboðum - Þegar verið er að semja skilaboð á einungis að birta farsímanúmer - Skilaboðum verður eytt eftir tiltekinn fjölda daga - Endur-samstilltu skilaboðin þín við innbyggðan SMS-gagnagrunn Android - Halda áfram í %s og afrita yfir þau númer sem þú hefur þegar útilokað - - Halda áfram í %s og útiloka þetta númer - Halda áfram í %s og útiloka þessi númer - - - Halda áfram í %s og leyfa þetta númer - Halda áfram í %s og leyfa þessi númer - - -Message/Skilaboð er SMS-skilaboðaforrit með opinn grunnkóða sem kemur í staðinn fyrir staðalforritið í Android. - Viðtakendur og svör verða sýnileg öllum - Þetta er upphafið á samtalinu. Segðu eitthvað fallegt! - Ertu viss um að þú viljir endurheimta skilaboðin þín úr þessu öryggisafriti\? - Sendu skilaboð sjálfvirkt, nákvæmlega á þeim tíma sem þér hentar - Skilaboð sem þegar hafa verið endurheimt munu verða eftir á tækinu þínu - Í augnablikinu er einungis stuðningur við öryggisafritun og endurheimtu SMS-skilaboða. Stuðningur við MMS og áætlaðar öryggisafritanir mun koma innan skamms! - Hæ! Hvenær var aftur afmælisdagurinn þinn\? - Það er þann 23. desember - Til hamingju með afmælið! Hvílíkur snillingur sem ég er að muna eftir afmælinu þínu - Sendi þann 23. desember  - QK-svar - Ef ekki tekst að senda lengri textaskilaboð, eða þau séu send í rangri röð, þá geturðu sent þau sem MMS-skilaboð. Það getur haft í för með sér aukinn kostnað - Innbyggð virkni útilokana í Skilaboð/Message - Lokaðu á ruslskilaboð, óumbeðin og óþekkt símanúmer með bannlista og áætlunum - Þakka þér kærlega fyrir að styðja QKSMS! - Þú hefur núna aðgang að öllum eiginleikum QKSMS+ - QKSMS+ er ókeypis fyrir notendur F-Droid users! Ef þú myndir vilja styrkja áframhaldandi þróun hugbúnaðarins, væri dálítill styrkur vel þeginn. - QK-svar - Þú getur bjargað hungruðum forritara fyrir svo lítið sem %s - Lífstíma-uppfærslur fyrir %1$s %2$s - Aflæsa + styrkja fyrir %1$s %2$s - Bíddu í nokkrar sekúndur áður en skilaboðin þín eru send - Útiloka skilaboð sem innihalda tiltekin stikkorð eða samsvara mynstrum - Áframsenda sjálfkrafa skilaboð frá tilteknum sendendum - Svara sjálfkrafa skilaboðum með forstilltu svari - QKSMS er í virkri þróun, innkaup þín innifela alla framtíðareiginleika QKSMS+! - Síaðu sjálfkrafa símtöl og skilaboð á einum hentugum stað! Samfélagið er með IQ™ gagnagrunn sem gerir þér kleift að hindra skilaboð frá ruslpóstsendendum sem samfélagið þekkir - Síaðu sjálfkrafa skilaboð frá óumbeðnum símanúmerum með því að nota \"Ætti ég að svara\" forritið - Hágæða-þemu - Aflæstu fallegum þemalitum sem ekki eru tiltækir á litaspjaldi Material-hönnunar - Búa til sérsniðin sjálfvirk emoji-tjáningartákn - Taktu sjálfvirkt öryggisafrit af skilaboðunum þínum. Hafðu ekki lengur áhyggjur af því að missa þráðinn ef þú skiptir um síma eða týnir honum - Þú getur tímasett skilaboðin þín til sendingar á tiltekinni dagsetningu eða tíma - \ No newline at end of file diff --git a/presentation/src/main/res/values-it/e_strings.xml b/presentation/src/main/res/values-it/e_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..6721d91fea26d193868be23106344a980610bb44 --- /dev/null +++ b/presentation/src/main/res/values-it/e_strings.xml @@ -0,0 +1,31 @@ + + + + Rendi Message la tua app di SMS predefinita + Message deve avere il permesso di inviare e visualizzare messaggi SMS + Message ha bisogno del permesso di visualizzare i contatti + Informazioni su Message + Message è un fork di QKSMS + Info su Messaggi + Versione App + - Message è un\'App open source che sostituisce la messaggistica standard di Android. + Privacy policy + Termini di servizio + Autori + Non è possibile aggiungere un numero vuoto! Ritenta + Non è possibile aggiungere un testo vuoto! Ritenta + \ No newline at end of file diff --git a/presentation/src/main/res/values-it/strings.xml b/presentation/src/main/res/values-it/strings.xml index e35dae76ee415e65cf0030f42173a48a445b88a5..a89d28572b52e07d76f0384d5b50fc0262f83bb8 100644 --- a/presentation/src/main/res/values-it/strings.xml +++ b/presentation/src/main/res/values-it/strings.xml @@ -1,5 +1,5 @@ - + --> + Nuova conversazione Componi Scelta rapida disattivata - Archiviato + Archivio Impostazioni Notifiche - Cerca in casella arrivo… + Tema + Cerca in posta in arrivo… Digita un nome o un numero Salta Continua + Aggiungi persona Chiama Dettagli Salva nella galleria - Apri barra di navigazione + Condividi + Apri il pannello di navigazione %d selezionato - Pulisci + Azzera Archivia Annulla archiviazione Elimina Aggiungi ai contatti Blocca in alto Sblocca - Segna come letto - Segna come da leggere - Blocca - Sincronizzo i messaggi… + Segna come \"letto\" + Segna come \"da leggere\" + Sposta negli indesiderati + La sincronizzazione dei messaggi… Tu: %s Bozza Risultati nei messaggi %d messaggi - Le tue conversazioni verranno visualizzate qui + Le tue conversazioni vengono visualizzate qui Nessun risultato - Le tue conversazioni archiviate verranno visualizzate qui + Le tue conversazioni vengono archiviate qui Inizia nuova conversazione - Adoro scrivere SMS - Rendi Message la tua app di SMS predefinita + Adoro scrivere di nuovo SMS + Rendi QKSMS la tua app di SMS predefinita Modifica Autorizzazione necessaria - Message deve avere il permesso di inviare e visualizzare messaggi SMS - Message ha bisogno del permesso di visualizzare i contatti + QKSMS ha bisogno dell\'autorizzazione per inviare e visualizzare gli SMS + QKSMS ha bisogno dell\'autorizzazione per visualizzare i tuoi contatti + QKSMS needs permission to display notifications Consenti Ricevuti Archiviati @@ -64,35 +69,44 @@ Indesiderati Altro Impostazioni - Help & feedback - Invita amici + Aiuto & suggerimenti + Invita gli amici + Sblocca nuove incredibili funzionalità e sostieni lo sviluppo + Ti piace QKSMS? + Condividi un po\' di amore e votaci su Google Play! + OK! + ANNULLA Elimina - Sei sicuro di voler eliminare questo messaggio\? - Sei sicuro di voler eliminare %d messaggi\? - Sei sicuro di voler eliminare %d messaggi\? + Sei sicuro di voler eliminare questa conversazione? + Sei sicuro di voler eliminare %d conversazioni? Copia testo Inoltra Elimina - %d selezionati + Scegli un numero di telefono + %s ∙ Predefinito + Solo una volta + Sempre + %d selezionato %1$d di %2$d risultati Invia come messaggio di gruppo - Destinatari e risposte saranno visibili a tutti - Questo è l\'inizio della conversazione. Dì qualcosa di carino! + I destinatari e le risposte saranno visibili a tutti + Questo è l\'inizio della tua conversazione. Dì qualcosa di carino! Scheda contatto Pianificato per - L\'orario scelto deve essere nel futuro! + L\'ora selezionata deve essere nel futuro! + È necessario sbloccare QKSMS+ per utilizzare la pianificazione dei messaggi Aggiunto ai messaggi pianificati - Scrivi un messaggio… + Scrivi un messaggio… Copia testo Inoltra Elimina Precedente Successivo - Cancella + Azzera Dettagli del messaggio Tipo: %s Da: %s @@ -108,60 +122,66 @@ Allega una foto Scatta una foto Pianifica messaggio - Allega un contatto - Errore di lettura del contatto - %s selezionato, cambia SIM + Collegare un contatto + Errore nella lettura del contatto + + SIM %1$d (%2$s) selezionata + %s selezionato, cambiare SIM Invia messaggio - Invio in corso… - %s consegnati - Invio non riuscito. Tocca per riprovare + Invio in corso… + Consegnato %s + Impossibile inviare. Tocca per riprovare Dettagli + Indirizzo copiato Titolo della conversazione Notifiche + Tema Archivia Annulla archiviazione - Blocca - Sblocca - Elimina conversazione + Mittente indesiderato + Ripristina mittente + Elimina la conversazione Impossibile caricare il supporto Salvato nella galleria Backup e ripristino Backup dei messaggi Ripristino da backup - Ultimo backup - Sto Caricando… + Caricamento… Mai + Backup location + Set folder Ripristino - Scegli il backup - Backup in corso… - Ripristino in corso… + Selezionare un backup + Si prega di sbloccare QKSMS + per utilizzare backup e ripristino + Backup in corso… + Ripristino in corso… Ripristino da backup - Sei sicuro di voler ripristinare i messaggi da questo backup\? Interrompi il ripristino I messaggi che sono già stati ripristinati rimarranno sul tuo dispositivo - Backup + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details + Backups Nessun backup trovato - - %d messaggio - %d messaggi - %d messaggi - - Attualmente Backup e Restore supportano solo SMS. Il supporto per gli MMS ed i backup pianificati arriveranno presto! + Attualmente Backup e Restore supportano solo gli SMS. Il supporto per gli MMS ed i backup schedulati arriverà presto! Backup adesso - Analisi del backup… + L\'analisi del backup… %d/%d messaggi - Salvataggio backup… - Sincronizzo i messaggi… + Salvataggio backup… + Sincronizzazione messaggi… Terminato! Backup e ripristino - Pianificati - Invia un messaggio automaticamente, nell\'istante desiderato - Ehi! Quando è il tuo compleanno\? + Messaggi pianificati + Invia un messaggio automatico, nel momento desiderato + Ehi! Quand\'è il tuo compleanno? È il 23 dicembre - Buon compleanno! Guarda che grande amico che sono, mi ricordo del tuo compleanno + Buon Compleanno! Solo un grande amico si ricorda il tuo compleanno - Invia il 23 Dicembre  - Pianifica un messaggio + Invio il 23 dicembre  + Schedula un messaggio Messaggio pianificato Invia ora @@ -170,27 +190,30 @@ Aspetto Generale - Risposta Rapida + Risposta QK + Tema Modalità notturna - Modalità notturna nero puro - Ora inizio - Ora fine + Modalità notte nero puro + Ora di inizio + Ora di fine + Colori dei contatti automatici Dimensione carattere - Usa il font di sistema + Usa il carattere di sistema Emoji automatico Notifiche - Tocca per personalizzare + Seleziona per personalizzare Azioni Pulsante 1 Pulsante 2 Pulsante 3 Anteprima delle notifiche + Schermata iniziale Vibrazione Suono Nessuno - Risposta Rapida - Popup per nuovi messaggi - Tocca per rimuovere + Risposta QK + Popup per i nuovi messaggi + Tocca per archiviare Tocca al di fuori del popup per chiuderlo Invio posticipato Azioni di scorrimento @@ -204,8 +227,8 @@ Elimina Blocca Chiama - Segna come letto - Segna come da leggere + Segna come \"letto\" + Segna come \"da leggere\" Conferme di recapito Conferma che i messaggi siano stati inviati con successo @@ -213,46 +236,57 @@ Aggiungi una firma alla fine dei tuoi messaggi Elimina gli accenti Rimuovi gli accenti dai caratteri negli SMS in uscita - Solo numeri di telefoni cellulari - Durante la composizione di un messaggio, visualizza solo i numeri di telefoni cellulari + Solo numeri mobili + Durante la composizione di un messaggio, visualizza solo i numeri di cellulare + Elimina automaticamente i vecchi messaggi + I messaggi verranno eliminati dopo il numero di giorni specificato + Numero di giorni + Mai + Eliminare i vecchi messaggi automaticamente? + Scegliendo di procedere, %1$d messaggi verranno eliminati ora + + Dopo 1 giorno + Dopo %d giorni + + Invia messaggi lunghi come MMS + Se i tuoi messaggi di testo più lunghi non vengono inviati o vengono inviati nell\'ordine sbagliato, puoi invece inviarli come messaggi MMS. Potrebbero essere applicati costi aggiuntivi Compressione automatica degli allegati MMS Sincronizza i messaggi Risincronizza i tuoi messaggi con il database SMS Android nativo - Informazioni su Message + Informazioni su QKSMS Versione %s - Attivata registrazione di debug - Disattivata registrazione di debug + Registrazione del debug attivata + Registrazione del debug disattivata Inserisci la durata (in secondi) - Sto bloccando + Bloccare Elimina messaggi Elimina i messaggi in arrivo dai mittenti bloccati invece di nasconderli Conversazioni bloccate Gestore blocchi QKSMS Funzionalità di blocco integrata in QKSMS - Filtra automaticamente le tue chiamate e i tuoi messaggi in un unico posto! Community IQ™ ti consente di prevenire messaggi indesiderati dagli spammer noti alla community + Blocca i messaggi di spam, i numeri e le chiamate sconosciute con la blacklist e con lo Scheduler + Filtra automaticamente le tue chiamate e i tuoi messaggi in un unico comodo posto! Community IQ™ ti consente di prevenire messaggi indesiderati dagli spammer noti alla comunità Filtrare automaticamente i messaggi provenienti da numeri indesiderati utilizzando l\'app \"Dovrei rispondere?\" Copia i numeri bloccati Continua a copiare %s sui tuoi numeri bloccati esistenti Numeri bloccati - I numeri bloccati verranno visulaizzati qui + I tuoi numeri bloccati appariranno qui Blocca un nuovo numero - Blocca i messaggi da + Blocca i testi da Numero di telefono Blocca Messaggi bloccati - I messaggi bloccati verranno visualizzati qui + I tuoi messaggi bloccati appariranno qui Blocca Sblocca - Continua fino a %s e blocca questo numero - Continua fino a %s e blocca questi numeri - Continua fino a %s e blocca questi numeri + Continua a %s e blocca questo numero + Continua a %s e blocca questi numeri - Continua fino a %s e permetti questo numero - Continua fino a %s e consenti questi numeri - Continua fino a %s e consenti questi numeri + Continua a %s e permetti questo numero + Continua a %s e consenti questi numeri Informazioni Versione @@ -263,44 +297,48 @@ Licenza Copyright Supporta lo sviluppo, sblocca tutte le funzioni - Puoi salvare uno sviluppatore affamato con soli %s + Salva uno sviluppatore affamato per soli %s Upgrade a vita per %1$s %2$s - Sblocca & dona %1$s %2$s + Sblocca & dona per %1$s %2$s Grazie per il supporto a QKSMS! - Ora hai accesso alle le funzioni QKSMS+ - QKSMS+ è gratuito per gli utenti di F-Droid! Se desideri sostenere il progetto, una donazione sarebbe molto apprezzata. - Dona con PayPal - In arrivo + È ora possibile accedere a tutte le funzioni QKSMS+ + Si è verificato un errore, si prega di riprovare + QKSMS+ è gratuito per gli utenti di F-Droid! Se desideri sostenere il progetto, una tua donazione sarebbe molto apprezzata. + Fai una donazione tramite PayPal + Prossimamente Temi Premium - Sblocca splendidi temi non disponibili nella tavolozza di Material Design + Sblocca splendidi colori non disponibili nella tavolozza del Material Design Personalizza gli emoji automatici Crea scorciatoie personalizzate per gli emoji automatici Backup dei messaggi - Effettua automaticamente il backup dei messaggi. Non dovrai più preoccuparti di poter perdere la cronologia se cambi il telefono o lo smarrisci + Effettua automaticamente il backup dei tuoi messaggi. Non dovrai più preoccuparti di perdere la cronologia quando cambi il telefono o lo perdi Messaggi pianificati Messaggi pianificati da inviare automaticamente ad una specifica data e ora Invio posticipato - Attendere alcuni secondi prima di inviare il messaggio + Attendere alcuni secondi prima di inviare il tuo messaggio Modalità notturna automatica Attiva la modalità notturna in base all\'ora del giorno Blocco avanzato Bloccare i messaggi che contengono parole chiave o corrispondono a modelli Inoltro automatico - Inoltra automaticamente i messaggi da determinati mittenti + Inoltrare automaticamente i messaggi da determinati mittenti Risposta automatica - Rispondi automaticamente ai messaggi in arrivo con una risposta predeterminata + Rispondere automaticamente ai messaggi in arrivo con una risposta preimpostata Altro - QKSMS è in sviluppo attivo, e l\'acquisto includerà tutte le caratteristiche future di QKSMS+! - Sto caricando… + QKSMS è sotto sviluppo attivo, e l\'acquisto includerà tutte le caratteristiche future di QKSMS+! + Caricamento… Mostra altre conversazioni - Segna come letto + Segna come \"letto\" Chiama Elimina - Mostra altro + Mostra dettagli Mostra meno Apri la conversazione + Material + HEX + Applica Nessuna Archivia @@ -321,12 +359,12 @@ Annulla Copiato Conversazione archiviata + È necessario sbloccare QKSMS+ per utilizzare questo Nuovo messaggio - %s nuovi messaggi %s nuovi messaggi - Messaggio non inviato + Messaggi non inviati Il messaggio a %s non è stato inviato Sistema @@ -347,9 +385,9 @@ Nessun ritardo - Breve - Medio - Lungo + 3 secondi + 5 secondi + 10 secondi Automatico @@ -375,53 +413,4 @@ LOL Va bene - Per utilizzarlo, devi sbloccare QKSMS+ - Autori - Termini di servizio - Privacy policy - Versione App - Info su Messaggi - Message - Tema - Condividi - Aggiungi persona - Tema - Non è possibile aggiungere un testo vuoto! Ritenta - Non è possibile aggiungere un numero vuoto! Ritenta - IGNORA - VA BENE! - Condividi un po\' di amore e votaci su Google Play! - Ti piace Message\? - Sblocca nuove incredibili funzioni e supporta lo sviluppo - Applica - HEX - Material - Si è verificato un errore, ritenta - - Message è un\'App open source che sostituisce la messaggistica standard di Android. - Message è un fork di QKSMS - Blocca messaggi di spam, numeri e chiamate sconosciute con blacklist & Schedule - Se i messaggi di testo lunghi non vengono inviati o vengono inviati nell\'ordine sbagliato, è possibile inviarli come messaggi MMS. Potrebbe generare costi aggiuntivi - Invia i messaggi lunghi come MMS - - Dopo 1 giorno - Dopo %d giorni - Dopo %d giorni - - Se procedi, verranno cancellati adesso %1$d messaggi - Cancello i messaggi vecchi automaticamente\? - Mai - Numero di giorni - I messaggi saranno cancellati dopo il numero di giorni indicati - Cancella vecchi messaggi automaticamente - Risveglia lo schermo - Colore dei contatti automatico - Sblocca QKSMS+ per usare backup and restore - Tema - Indirizzo copiato - SIM %1$d (%2$s) selezionata - Per usare la messaggistica pianificata devi sbloccare QKSMS+ - Sempre - Solo una volta - %s ∙ Default - Scegli un numero di telefono diff --git a/presentation/src/main/res/values-iw/e_strings.xml b/presentation/src/main/res/values-iw/e_strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..0ae116df5a66d2af5a7fffc42892d6d3ef70d696 --- /dev/null +++ b/presentation/src/main/res/values-iw/e_strings.xml @@ -0,0 +1,22 @@ + + + + הגדרת Message ליישומון המסרונים כבררת מחדל + ל־Message נדרשות הרשאות כדי לשלוח ולצפות במסרונים + ל־Message נדרשות הרשאות כדי לצפות באנשי הקשר שלך + על אודות Message + \ No newline at end of file diff --git a/presentation/src/main/res/values-iw/strings.xml b/presentation/src/main/res/values-iw/strings.xml index c9b90a13018090da6c16adf114c20bf1aed61eda..c11f6025078117fddc70fed5e7b5e1644df8e1c2 100644 --- a/presentation/src/main/res/values-iw/strings.xml +++ b/presentation/src/main/res/values-iw/strings.xml @@ -1,5 +1,4 @@ - התכתבות חדשה - כתיבה + כתוב הודעה קיצור הדרך הושבת בארכיון הגדרות התראות - חיפוש בדואר הנכנס… - כתוב הודעה - דילוג + ערכת נושא + חיפוש בהודעות נכנסות… + נא להקליד שם או מספר + דלג המשך - התקשר + הוסף איש קשר + התקשרות פרטים - שמירה לגלריה - פתיחת מגירת ניווט + שמור לגלריה + שיתוף + פתח מגירת ניווט %d נבחרו - פינוי + נקה לארכיון שליפה מהארכיון - מחיקה - הוספה לאנשי קשר - הצמדה למעלה - שחרור הצמדה - סימון כנקרא - סימון כלא נקרא - חסימה - ההודעות מסונכרנות… - אני: %s - טיוטה: %s + מחק + הוסף לאנשי קשר + הצמד למעלה + בטל הצמדה + סמן כהודעה שנקראה + סמן כהודעה שלא נקראה + חסום + מסנכרן הודעות… + אתה: %s + טיוטה תוצאות בהודעות %d הודעות - ההתכתבויות של תופענה כאן + ההתכתבויות שלך תופענה כאן אין תוצאות ההתכתבויות שהעברת לארכיון תופענה כאן התחלת התכתבות חדשה - להתאהב בהתכתבות - הגדרת Message ליישומון המסרונים כבררת מחדל - החלפה + להתאהב מחדש בכתיבת הודעות + הגדרת QKSMS כיישומון בררת מחדל למסרונים + החלף נדרשת הרשאה - ל־Message נדרשות הרשאות כדי לשלוח ולצפות במסרונים - ל־Message נדרשות הרשאות כדי לצפות באנשי הקשר שלך - לאפשר + ל־QKSMS נדרשות הרשאות כדי לשלוח ולצפות במסרונים + ל־QKSMS נדרשות הרשאות כדי לצפות באנשי הקשר שלך + ל־QKSMS דרושות הרשאות כדי להציג התראות + אפשר דואר נכנס בארכיון - בתזמון + מתוזמן חסימה עוד הגדרות עזרה ומשוב הזמנת חברים - מחיקה + לחשוף תכונות מדהימות ולתמוך בפיתוח + QKSMS נושא חן בעיניך? + נשמח לקבל ממך דירוג ב־Google Play! + כמובן! + התעלמות + מחק - למחוק את ההתכתבות הזאת? + אתה בטוח שברצונך למחוק ההתכתבות זאת? למחוק את %d ההתכתבויות האלה? למחוק את %d ההתכתבויות האלה? למחוק את %d ההתכתבויות האלה? - העתקת טקסט - העברה - מחיקה + העתק טקסט + העבר + מחק + נא לבחור מספר טלפון + %s ∙ ברירת מחדל + פעם אחד בלבד + תמיד %d נבחרו %1$d מתוך %2$d תוצאות שליחה כהודעה קבוצתית @@ -88,14 +100,15 @@ כרטיס קשר מתוזמן למועד הזמן הנבחר חייב להיות בעתיד! + עליך לשחרר את QKSMS+‎ כדי להשתמש בהודעות מתוזמנות הוספה להודעות המתוזמנות - כתיבת הודעה… - העתקת טקסט - העברה - מחיקה - הקודמת - הבאה - פינוי + כתוב הודעה… + העתק טקסט + העבר + מחק + הקודם + הבא + נקה פרטי הודעה סוג: %s מאת: %s @@ -103,63 +116,68 @@ נושא: %s עדיפות: %s גודל: %s - שליחה: %s - קבלה: %s - מסירה: %s + נשלח: %s + התקבל: %s + נמסר: %s קוד שגיאה: %d - הוספת קובץ מצורף - צירוף תמונה - צילום תמונה + הוסף קובץ מצורף + צרף תמונה + צלם תמונה תזמון הודעה - צירוף איש קשר + צרף איש קשר שגיאה בקריאת איש קשר - %s נבחרו, החלפת כרטיס SIM - שליחת הודעה - מתבצעת שליחה… + + נבחר SIM מס׳ %1$d ‏(%2$s) + %s נבחר, החלף כרטיס SIM + שלח הודעה + שולח… %s נמסרה - השליחה נכשלה. נא לגעת כדי לנסות שוב + השליחה נכשלה. הקש כדי לנסות שוב פרטים + הכתובת הועתקה כותרת התכתבות התראות - העברה לארכיון + ערכת נושא + ארכיון הוצאה מארכיון - חסימה - שחרור חסימה - מחיקת התכתבות + חסום + בטל חסימה + מחק התכתבות לא ניתן לטעון מדיה נשמר לגלריה גיבוי ושחזור - ההודעות מגובות - מתבצע שחזור מגיבוי - גיבוי אחרון - בטעינה… - מעולם לא + מגבה הודעות + משחזר מגיבוי + טוען… + לעולם לא + מיקום הגיבוי + הגדרת תיקייה שחזור - בחירת גיבוי + בחר גיבוי + נא לשחרר את QKSMS+‎ כדי להשתמש בגיבוי ובשחזור מתבצע גיבוי… מתבצע שחזור… - שחזור מגיבוי - לשחזר את ההודעות שלך מהגיבוי הזה? - עצירת השחזור + שחזר מגיבוי + עצור שחזור הודעות שכבר שוחזרו יישארו במכשיר שלך + בחירת מיקום לשמירת הגיבוי + נא לבחור תיקייה אלייה יישמרו הגיבויים שלך + %1$s\n%2$d הודעות + שגיאה + לא ניתן לקרוא את קובץ הגיבוי + פרטי גיבוי גיבויים לא נמצאו גיבויים - - הודעה אחת - שתי הודעות - %d הודעות - %d הודעות - נכון לעכשיו, קיימת תמיכה בהודעות מסוג SMS בתכונת הגיבוי והשחזור. תמיכה ב־MMS וגיבויים מתוזמנים יגיעו בעתיד הקרוב! - לגבות כעת + גבה כעת הגיבוי מפוענח… %d/%d הודעות - הגיבוי נשמר… - ההודעות מסונכרנות… + שומר גיבוי… + מסנכרן הודעות… הסתיים! גיבוי ושחזור - מתוזמנת - שליחת הודעה אוטומטית, ברגע המדויק שמתאים לך + מתוזמן + שלח הודעה אוטומטית, ברגע המדויק שמתאים לך היי! מתי יום ההולדת שלך שוב? ב־23 בדצמבר מזל טוב! תראה איך החברות בינינו פורחת, זכרתי את יום ההולדת שלך @@ -168,47 +186,51 @@ תזמון הודעה הודעה מתוזמנת - לשלוח כע - העתקת טקסט - מחיקה + שלח כעת + העתק טקסט + מחק מראה כללי תגובה מהירה + ערכת נושא מצב לילה מצב לילה שחור טהור זמן התחלה זמן סיום + צבעים אוטומטיים לאנשי קשר גודל גופן שימוש בגופן המערכת אימוג׳י אוטומטי התראות - יש לגעת כדי להתאים אישית + הקש כדי להתאים אישית פעולות כפתור 1 כפתור 2 כפתור 3 תצוגות מקדימות של התראות + הפעלת המסך רטט צליל ללא תגובה מהירה חלונית קופצת להודעות חדשות - יש לגעת כדי להתעלם - יש לגעת מחוץ לחלונית הקופצת כדי לסגור אותה + הקש כדי להתעלם + הקש מחוץ לחלונית הקופצת כדי לסגור אותה שליחה בעיכוב - פעולות גרירה - להגדיר פעולות גרירה לדיונים - גרירה ימינה - גרירה שמאלה + פעולות ניגוב + הגדר פעולות ניגוב להתכתבויות + ניגוב ימינה + ניגוב שמאלה החלפה ללא לארכיון - מחיקה - התקשרות - סימון כנקרא - סימון כלא נקרא + מחק + חסום + התקשר + סמן כהודעה שנקראה + סמן כהודעה שלא נקראה אישור מסירה אישור שההודעות נשלחו בהצלחה @@ -218,10 +240,24 @@ הסרת סימנים דיאקריטיים מתווים במסרונים יוצאים מספרי ניידים בלבד בעת כתיבת הודעה, להציג רק מספרי טלפון של ניידים + למחוק הודעות ישנות אוטומטית + הודעות תימחקנה לאחר כמות מסוימת של ימים + מספר הימים + אף פעם + למחוק הודעות ישנות אוטומטית? + המשך הפעולה יוביל למחיקת %1$d הודעות כעת + + לאחר יום + לאחר יומיים + לאחר %d ימים + לאחר %d ימים + + לשלוח הודעות ארוכות כ־MMS + אם יש לך בעיה בשליחת הודעות טקסט ארוכות יותר או בעיה ברצף שליחת ההודעה, ניתן לשלוח כהודעת MMS במקום. עלול לגרור עלויות נוספות דחיסה אוטומטית של קבצים מצורפים להודעות MMS סנכרון הודעות סנכרון ההודעות שלך מחדש עם מסד הנתונים המובנה של Android - על אודות Message + על אודות QKSMS גרסה %s תיעוד ניפוי שגיאות פעיל תיעוד ניפוי שגיאות כבוי @@ -229,10 +265,11 @@ חסימה השמטת הודעות להשמיט הודעות נכנסות משולחים חסומים במקום להסתיר אותן - דיונים חסומים + התכתבויות חסומות מנהל חסימות QKSMS תכונת חסימה מובנית בתוך QKSMS + חסימת הודעות ספאם, מספרים ושיחות לא מזוהות עם רשימת חסימה ותזמון לסנן אוטומטית את השיחות וההודעות שלך במקום אחיד ונוח! Community IQ™‎ מאפשר לך להימנע מהודעות בלתי רצויות בזכות דיווחים על מפיצי ספאם מצד הקהילה לסנן אוטומטית הודעות ממספרים בלתי רצויים על ידי שימוש ביישומון „Should I Answer” (שאענה) העתקת מספרים חסומים @@ -275,6 +312,7 @@ שחרור ותרומה תמורת %1$s %2$s תודה לך על תמיכתך ב־QKSMS! כעת יש לך גישה לכל התכונות של QKSMS+‎ + אירעה שגיאה, נא לנסות שוב התכנית QKSMS+‎ מוגשת בחינם למשתמשי F-Droid! אם מעניין אותך לתמוך בפיתוח, אפשר להגיש תרומה. תרומה באמצעות PayPal בקרוב @@ -300,12 +338,15 @@ הפיתוח של QKSMS מתקיים בימים אלו והרכישה שלך תכלול את כל התכונות העתידיות של QKSMS+‎! בטעינה… הצגת התכתבויות נוספות - לסמן כנקראה + סימון כהודעה שנקראה להתקשר מחיקה להציג יותר להציג פחות - פתיחת דיון + פתיחת התכתבות + Material + הקסה + החלה ללא לארכיון @@ -325,7 +366,8 @@ הגדרה ביטול הועתק - דיון בארכיון + התכתבות בארכיון + עליך לשחרר את QKSMS+‎ כדי להשתמש בזה הודעה חדשה %s הודעות חדשות @@ -353,9 +395,9 @@ ללא השהיה - קצרה - בינונית - ארוכה + 3 שניות + 5 שניות + 10 שניות אוטומטי diff --git a/presentation/src/main/res/values-ja/strings.xml b/presentation/src/main/res/values-ja/strings.xml index fe9737266f03fe0b141040da267db39950270063..997b14ab401256c83cdc1e4973b66d4bbb8e33d9 100644 --- a/presentation/src/main/res/values-ja/strings.xml +++ b/presentation/src/main/res/values-ja/strings.xml @@ -1,5 +1,4 @@ - 新しい会話 - メッセージを書く - 無効にするショートカット - アーカイブ済 + 新規作成 + ショートカットが無効です + アーカイブ済み 設定 通知 + テーマ 受信トレイを検索… - 作成 + 名前または電話番号を入力 スキップ 続行 + 人物を追加 通話 詳細 ギャラリーに保存 - ナビゲーション引き出しを開く - %d 選択された - 消去しました + 共有 + ナビゲーションドロワーを開く + %d 件を選択中 + 消去 アーカイブ - アーカイブしない + アーカイブ解除 削除 連絡先に追加 - 上部に固定します。 - 固定を解除します。 + 上部に固定 + 固定を解除 既読にする 未読にする ブロック - 同期メッセージ… + メッセージを同期しています... あなた: %s - ドラフト: %s - メッセージの結果 - %d メッセージ + 下書き + メッセージ内の検索結果 + %d 件のメッセージ 会話がここに表示されます - 結果はありません + 検索結果がありません 保存した会話がここに表示されます - 新しい会話を開始します。 - もう一度テキストメッセージが大好き - Message のデフォルトの SMS アプリを作る + 新しい会話を開始 + もう一度テキストメッセージが好きになる + QKSMS を既定の SMS アプリに設定 変更 - 必要なアクセス許可 - MessageはSMSメッセージを送信および表示する権限を必要とします - Messageはあなたの連絡先を閲覧する許可を必要とします - 許可する + アクセス権限を許可してください + QKSMS は SMS メッセージを送信および表示する権限を必要とします + QKSMS はあなたの連絡先を閲覧する権限を必要とします + QKSMS は通知を表示する権限を必要とします + 許可 受信トレイ - アーカイブ済 - スケジュール済 + アーカイブ済み + 送信予約済み ブロック もっと 設定 ヘルプとフィードバック - 友達を招待する + 友達を招待 + 素敵な新機能を解放して、開発をサポート + QKSMS をお楽みいただいていますか? + Google Play で愛を共有して私たちを評価してください! + OK! + 非表示 削除 - %d の会話を削除するよろしいですか。 + 本当に %d 件の会話を削除しますか? テキストをコピー 転送 削除 - %d件を選択中 - %2$d 結果の %1$d - グループ メッセージとして送信します。 - 受信者と返信は全員に表示されます - これが会話の始まりです。 何か素敵なことを言ってください! + 電話番号を選択 + %s ∙ デフォルト + 1 回だけ + 常に + %d 件を選択中 + %2$d 件中 %1$d 件の結果 + グループ メッセージとして送信 + 宛先と返信は全員に表示されます + これが会話の始まりです。何か素敵なことを言ってください! 連絡先カード - 予定されている - 選択した時間は、将来的にする必要があります! - スケジュールされたメッセージに追加 - メッセージを書く… - テキストのコピー + 送信予約 + 今より先の時間を選択してください! + メッセージの送信予約には、QKSMS+ のロックを解除する必要があります + 送信予約メッセージに追加されました + メッセージを書いてください… + テキストをコピー 転送 削除 前へ @@ -95,72 +108,80 @@ 消去 メッセージの詳細 タイプ: %s - 宛先: %s + 差出人: %s 宛先:%s 件名: %s - 優先順位: %s + 優先度: %s サイズ: %s - 送られた: %s - 受け取った: %s - 配達: %s - エラーコード:%d - 添付ファイルを追加する - 写真を添付する + 送信: %s + 受信: %s + 配信: %s + エラーコード: %d + 添付ファイルを追加 + 写真を添付 写真を撮る - スケジュールメッセージ - 連絡先を添付する + メッセージの送信を予約 + 連絡先を添付 連絡先の読み取りエラー - %s 選択、SIMカードを交換 - メッセージを送る + + SIM %1$d (%2$s) を選択しました + %s 選択、SIM カードを変更 + メッセージを送信 送信中… %s を配信しました 送信に失敗しました。タップすると、もう一度やり直します 詳細 + アドレスをコピーしました 会話のタイトル 通知 + テーマ アーカイブ アーカイブ解除 ブロック - ブロックを解除 + ブロック解除 会話を削除 メディアを読み込めませんでした ギャラリーに保存 バックアップと復元 - メッセージをバックアップする - バックアップからの復元 - 最後のバックアップ - ロード中... - 決して - リストア + メッセージをバックアップしています + バックアップから復元 + 読み込み中... + なし + バックアップの場所 + フォルダーを設定 + 復元 バックアップを選択 + バックアップと復元を使用するには QKSMS+ のロックを解除してください バックアップ中… 復元中… バックアップから復元 - このバックアップからメッセージを復元してもよろしいですか? - 復元を停止する + 復元を停止 既に復元されたメッセージはあなたのデバイスに残ります + バックアップの場所を選択 + バックアップを保存するフォルダーを選択してください + %1$s\n%2$d メッセージ + エラー + バックアップファイルを読み込めませんでした + バックアップの詳細 バックアップ バックアップが見つかりません - - %d メッセージ - - 現在、SMSのみがバックアップと復元でサポートされています。 MMSのサポートと定期的なバックアップは近日中に開始されます。 + 現在、SMS のみバックアップと復元に対応しています。 MMS 対応と定期バックアップは近日中に公開されます! 今すぐバックアップ - バックアップの解析中... - %d/%dすべてのメッセージ + バックアップを解析中... + %d 件/%d 件のメッセージ バックアップを保存しています... メッセージを同期しています... - 終了しました。 + 終了しました! バックアップと復元 - 予定 - 希望する瞬間に自動的にメッセージを送信する + 予約 + 希望する瞬間に自動的にメッセージを送信 ちょっと!あなたの誕生日はいつでしたか? - 12月23日です - お誕生日おめでとうございます! 私はあなたの誕生日を思い出して、何という素晴らしい友達なのか見て + 12 月 23 日です + お誕生日おめでとうございます! 私はあなたの誕生日を覚えている、素敵な友達でしょ? - 12月23日に発送 - メッセージをスケジュールする - スケジュールされたメッセージ + 12 月 23 日に送信 + メッセージを送信予約 + 送信予約されたメッセージ 今すぐ送る テキストをコピー @@ -168,36 +189,39 @@ 外観 全般 - QK 返信 + QK Reply + テーマ 夜間モード ピュアブラック夜間モード 開始時刻 終了時刻 + 自動的に連絡先に色をつける フォントサイズ システムフォントを使用する 自動絵文字 通知 - カスタマイズするためにタップ + タップしてカスタマイズ アクション ボタン 1 ボタン 2 ボタン 3 通知プレビュー - 振動 - サウンド - 無し - QK 返信 - 新しいメッセージのポップアップ + 画面を点灯 + バイブレーション + + なし + QK Reply + 新しいメッセージをポップアップ タップして閉じる ポップアップの外側をタップすると閉じます 遅延送信 スワイプアクション - 会話のスワイプアクションを設定する + 会話のスワイプアクションを設定 右スワイプ 左スワイプ 変更 - 無し + なし アーカイブ 削除 ブロック @@ -213,13 +237,24 @@ 送信する SMS メッセージの文字からアクセントを削除します 携帯電話番号のみ メッセージを作成するときは、携帯電話番号のみを表示します - MMS添付ファイルの自動圧縮 + 古いメッセージを自動的に削除 + 指定された日数の後にメッセージが削除されます + 日数 + 自動削除しない + 古いメッセージを自動的に削除しますか? + 続行すると、今すぐ %1$d 件のメッセージが削除されます + + %d 日後 + + 長いメッセージを MMS として送信 + 長いテキストメッセージの送信が失敗する場合、または間違った順序で送信される場合は、代わりに MMS メッセージとして送信できます。 追加料金が適用される場合があります + MMS 添付ファイルの自動圧縮 メッセージを同期 メッセージをネイティブの Android SMS データベースと再同期します - Message について + QKSMS について バージョン %s デバッグログが有効 - デバッグログを無効にする + デバッグログが無効 期間を入力してください (秒) ブロック メッセージをドロップ @@ -228,10 +263,11 @@ ブロッキングマネージャー QKSMS QKSMS の内蔵ブロック機能 - 一か所で便利に通話とメッセージを自動的にフィルタリングします! Community IQ™を使用すると、コミュニティで知られているスパマーからの不要なメッセージを防ぐことができます - \"Should I Answer\" アプリを使用して、迷惑な番号からのメッセージを自動的にフィルタします + ブラックリストにより迷惑メッセージ、番号、不明な通話をブロック + 1 か所で便利に通話とメッセージを自動的にフィルタリングします! Community IQ™を使用すると、コミュニティで知られているスパマーからの不要なメッセージを防ぐことができます + \"Should I Answer\" アプリを使用して、迷惑な番号からのメッセージを自動的にフィルターします ブロックした番号をコピー - 既存のブロックした番号のコピーを %s まで続けます + %s で継続して既存のブロックした番号をコピー ブロックした番号 ブロックした番号がここに表示されます 新しい番号をブロック @@ -243,10 +279,10 @@ ブロック ブロック解除 - %s まで続けてこの番号をブロック + %s で継続してこの番号をブロック - %s まで続けてこの番号を許可 + %s で継続してこの番号を許可 このアプリについて バージョン @@ -256,47 +292,51 @@ お問い合わせ ライセンス 著作権 - 開発をサポートして、すべてのロックを解除します - ちょうど %s 人の飢えている開発者を助けることができます + 開発をサポートして、すべての機能のロックを解除 + %s だけ飢えている開発者を助けることができます - %1$s %2$s のライフタイムのアップグレード + %1$s %2$s で買い切りのアップグレード - %1$s %2$s のロック解除と寄付 - QKSMS を支援いただきありがとうございます! + %1$s %2$s でロック解除と寄付 + QKSMS を支援いただきありがとうございます! QKSMS+ のすべての機能にアクセスできます - QKSMS+ は F-Droid ユーザーは無料です! 開発をサポートしたい場合は、気軽に寄付をしてください。 - PayPal で寄付する + エラーが発生しました。もう一度やり直してください + QKSMS+ は F-Droid ユーザーには無料です!開発をサポートしたい場合は、気軽に寄付をしてください。 + PayPal で寄付 近日登場 プレミアムテーマ マテリアルデザインパレットで利用できない美しいテーマカラーのロックを解除します カスタム自動絵文字 カスタム自動絵文字のショートカットを作成します メッセージのバックアップ - メッセージを自動的にバックアップします。携帯電話を変更したり、お使いの携帯電話をなくしても、もう二度と履歴がなくなる心配はいりません。 - スケジュールされたメッセージ - 特定の日時に自動的に送信されるようにメッセージをスケジュールする - 送信を遅らせる + メッセージを自動的にバックアップします。携帯電話を変更したり、お使いの携帯電話をなくしても、もう二度と履歴がなくなる心配はいりません + 送信予約メッセージ + メッセージが特定の日時に自動的に送信されるように予約する + 遅延送信 メッセージを送信する前に、数秒間待ちます 自動夜間モード 時間に基づいて夜間モードを有効にします 高度なブロック キーワードを含む、またはパターンに一致するメッセージをブロックします 自動転送 - 特定の送信者からのメッセージを自動的に転送します + 特定の差出人からのメッセージを自動的に転送します 自動応答 あらかじめ設定された応答で、受信したメッセージに自動的に返信します - さらに - QKMSは活発に開発中です、そして、あなたの購入はすべての将来のQKMS+機能を含みます! - ロード中... + その他 + QKSMS は活発に開発中で、購入にはすべての将来の QKSMS+ 機能が含まれます! + 読み込み中... さらに会話を表示 既読にする - 電話する + 通話 削除 - もっと見せる - 少なく表示 + 表示を増やす + 表示を減らす 会話を開く + マテリアル + 16 進数 + 適用 - 無し + なし アーカイブ 削除 ブロック @@ -308,22 +348,23 @@ 続行 キャンセル 削除 - 保存する + 保存 やめる さらに - 据える + 設定 元に戻す コピーしました 会話をアーカイブしました + 使用するには QKSMS+ のロックを解除する必要があります - %s 新着メッセージ + %s 件の新着メッセージ メッセージは送信されませんでした %s へのメッセージの送信に失敗しました システム 無効 - 常にON + 常に ON 自動 @@ -332,16 +373,16 @@ コンテンツを隠す - 小さい - 普通の - 大き - 大きい + + 標準 + + 最大 遅延なし - 短い - ミディアム - 長い + 3 秒 + 5 秒 + 10 秒 自動 @@ -355,16 +396,16 @@ OK - しばらくお待ちください + ちょっと待って 今、途中です ありがとう - 良さそうですね - 最近どうですか? + いいですね + 最近どうですか? 了解 いいえ 好きです ごめんなさい - 大爆笑です - いいんだよ + 爆笑 + 大丈夫 diff --git a/presentation/src/main/res/values-ko/strings.xml b/presentation/src/main/res/values-ko/strings.xml index 6bd55122c97d89b75decaa5661f87f81083ad75c..462472ef62584623a7dd902929c86af36b8d2a57 100644 --- a/presentation/src/main/res/values-ko/strings.xml +++ b/presentation/src/main/res/values-ko/strings.xml @@ -1,5 +1,4 @@ - + SIM %1$d (%2$s) 선택 됨 %s 선택됨, SIM 카드를 변경하세요. 메시지 보내기 전송 중... %s 전송됨 전송 실패, 눌러서 다시 시도하세요 자세히 + 주소 복사 됨 대화 제목 알림 + 테마 보관 보관 해제 차단 차단 해제 대화 삭제 미디어를 불러올 수 없습니다 - 갤러리에 저장 + 갤러리에 저장하기 백업과 복원 메시지 백업하기 복원하기 - 최근 백업 로딩 중... 사용 안 함 + Backup location + Set folder 복원 백업 선택하기 + QKSMS+을 구입하여 백업과 복원기능을 사용하세요 백업 중... 복원 중... - 복원이 되었습니다 - 이 백업 파일로부터 복원하시겠어요? + 복원을 할까요? 복원 중지 이미 저장된 메시지들은 내 기기에 남아있습니다. + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details 백업 백업을 찾지 못했어요 - - %d 개의 새로운 메시지 - 아직 SMS만 백업과 복원기능이 지원됩니다. MMS지원과 백업 스케줄 기능은 곧 찾아옵니다! 지금 백업하기 분석 중... @@ -155,43 +174,46 @@ 끝! 백업과 복원 예약됨 - 원하는 그 시간에 자동으로 메시지를 보냅니다. - 잠깐만요! 생일이 언제였나요..? - 12 월 23 일 입니다 - 생일 축하해요! 당신의 생일을 기억하는 멋진 친구죠..? + 원하는 시간에 자동으로 메시지를 보냅니다. + 잠깐만! 생일이 언제였더라..? + 12월 23일이야 + 생일 축하해! 너의 생일까지 기억해주는 이렇게 좋은 친구가 어디있겠어 - 12 월 23 일에 보냅니다. + 12월 23일에 보냅니다. 메시지 예약 전송하기 예약된 메시지 지금 보내기 - Copy text - Delete + 텍스트 복사하기 + 삭제 - 외관 + 디자인 일반 설정 빠른 응답 + 테마 나이트 모드 완전한 블랙 테마 시작 시간 끝나는 시간 + 연락처 색 자동 설정 글꼴 크기 시스템 글꼴 사용 자동 이모티콘 알림 - 사용자 지정 탭 + 탭해서 사용자화 동작 버튼 1 버튼 2 버튼 3 알림 미리 보기 + 화면 깨우기 진동 소리 없음 - 빠른 응답 + QK Reply 새로운 메시지에 대한 팝업 탭해서 닫기 - 아무곳을 터치하면 팝업이 닫힙니다. + 아무데나 탭하면 팝업이 닫힙니다. 전송 지연 쓸어넘기기 설정 대화를 쓸어넘겼을 때 할 작업 @@ -209,46 +231,58 @@ 전송 확인 전송 성공을 확인합니다 - Signature - Add a signature to the end of your messages + 서명 + 문자 메시지 마지막에 서명을 추가합니다 스트립 악센트 SMS를 주고받을 때, 대문자 없애기 전화번호만 보이기 메시지를 쓸 때, 전화번호만 보이게 하기 + 자동으로 오래된 메시지 제거 + 지정된 일 수 후에 메시지를 삭제합니다 + 일 수 + 사용 안 함 + 자동으로 오래된 메시지를 제거하시겠습니까? + 이대로 진행하면, %1$d 개의 메시지가 지금 삭제됩니다 + + %d 일 후 + + 장문 메시지를 MMS로 보내기 + 만약 장문의 메시지가 보내지지 않거나, 잘못된 순서로 보내진다면, MMS 메시지로 보낼 수 있습니다. (MMS로 인한 추가요금이 발생할 수 있습니다) 자동으로 MMS 첨부 파일 압축하기 - 메시지 동기화 하기 + 메시지 동기화하기 기본 안드로이드 SMS 데이터베이스에 다시 동기화하기 - Message에 대해... + QKSMS에 대해... 버전 정보 %s 디버그 로깅 설정됨 디버그 로깅 해제됨 기간 (초)을 입력 - Blocking - Drop messages - Drop incoming messages from blocked senders instead of hiding them - Blocked conversations - Blocking Manager + 차단 + 메시지 자동 삭제 + 차단된 사람으로부터 오는 메시지를 가리는 대신 삭제합니다 + 차단된 대화 + 차단 메니저 QKSMS - Built-in blocking functionality in QKSMS - Automatically filter your calls and messages in one convenient place! Community IQ™ allows you to prevent unwanted messages from community known spammers + 빌트인 차단기능이 있는 기본 필터. + Block spam messages, numbers & unknown calls with blacklist & Schedule + 자동으오 전화와 메시지를 한 곳에서 필터링하세요! Community IQ™는 커뮤니티 기반으로 원하지 않는 스팸 메시지를 차단해줍니다. Should I Answer 앱을 이용해 필요없는 번호에서 보낸 메시지를 자동으로 필터링하기 - Copy blocked numbers - Continue to %s and copy over your existing blocked numbers - Blocked numbers - Your blocked numbers will appear here - Block a new number - Block texts from - Phone number - Block - Blocked messages - Your blocked messages will appear here - Block - Unblock + 차단된 번호 복사하기 + %s로 계속하고 이미 차단된 번호를 복사합니다. + 차단된 번호 + 차단한 번호가 여기에 나타납니다 + 새로운 번호 차단하기 + 차단할 번호 입력 + 전화번호 + 차단 + 차단된 메시지 + 차단된 메시지가 여기에 나옵니다. + 차단 + 차단해제 - Continue to %s and block these numbers + %s 하고 이 번호 차단하기 - Continue to %s and allow these numbers + %s 하고 이 번호 허용하기 정보 버전 @@ -266,6 +300,7 @@ %1$s %2$s 으로 프리미엄 기능 잠금 해제 및 기부 QKSMS를 지원해 주셔서 감사합니다! 이제 모든 QKSMS+ 기능에 액세스할 수 있습니다 + An error has occurred, please try again QKSMS+는 F-Droid 사용자들에게 무료입니다! 만약 여러분이 개발을 지원하고 싶으시다면, 기부해 주시기 바랍니다. 페이팔을 통해 기부 출시 예정 @@ -297,6 +332,9 @@ 더 보기 적게 표시 대화 열기 + Meterial + HEX + 적용하기 없음 보관 @@ -306,8 +344,8 @@ 읽음으로 표시 답장 - Yes - Continue + + 계속 취소 삭제 저장 @@ -317,6 +355,7 @@ 되돌리기 복사됨 보관된 대화 + 이 기능을 사용하려면 QKSMS+ 를 잠금 해제해야 합니다. 새로운 메세지 @@ -325,10 +364,10 @@ 메시지 전송 실패 %s 에게 보낼 메시지 전송이 실패했습니다 - System - Disabled - Always on - Automatic + 시스템 설정 + 사용 안 함 + 항상 켬 + 자동 이름 및 메시지 표시 @@ -343,9 +382,9 @@ 지연 없음 - 짧게 - 중간 - 길게 + 3초 + 5초 + 10초 자동 diff --git a/presentation/src/main/res/values-lt/strings.xml b/presentation/src/main/res/values-lt/strings.xml index 874c2e66ae7abf094046bcb6e808b2b27b069df0..d6013bb8d1d4f0a4d4e70edbb21d18c6e00537dd 100644 --- a/presentation/src/main/res/values-lt/strings.xml +++ b/presentation/src/main/res/values-lt/strings.xml @@ -24,6 +24,7 @@ Archyvas Nustatymai Pranešimai + Spalva Ieškoti žinutes… Rašyti Praleisti @@ -55,11 +56,12 @@ Tavo archyvuoti pokalbiai bus čia Pradėti naują pokalbį Love texting again - Make Message your default SMS app + Make QKSMS your default SMS app Change Permission required - Message needs permission to send and view SMS messages - Message needs permission to view your contacts + QKSMS needs permission to send and view SMS messages + QKSMS needs permission to view your contacts + QKSMS needs permission to display notifications Allow Žinutės Archyvas @@ -69,6 +71,11 @@ Nustatymai Pagalba ir atsiliepimai Invite friends + Unlock amazing new features, and support development + Patinka QKSMS? + Įvertink mūsų programėlę Google Play! + OK! + ATMESTI Ištrinti Are you sure you would like to delete this conversation? @@ -93,6 +100,7 @@ Contact card Scheduled for Selected time must be in the future! + You must unlock QKSMS+ to use scheduled messaging Added to scheduled messages Rašyti žinutę... Kopijuoti tekstą @@ -129,6 +137,7 @@ Address copied Conversation title Pranešimai + Tema Archyvuoti Išarchyvuoti Blokuoti @@ -139,25 +148,26 @@ Backup and restore Backing up messages Restoring from backup - Last backup Loading… Never + Backup location + Set folder Restore Select a backup + Please unlock QKSMS+ to use backup and restore Backup in progress… Restore in progress… Restore from backup - Are you sure you would like to restore your messages from this backup? Stop restore Messages that have already been restored will remain on your device + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details Backups No backups found - - %d message - %d messages - %d messages - %d messages - Currently, only SMS is supported by Backup and Restore. MMS support and scheduled backups will be coming soon! Backup now Parsing backup… @@ -183,6 +193,7 @@ Išvaizda Bendra Greitas atsakas + Tema Nakties tema Visiškai juoda nakties tema Pradžios laikas @@ -246,7 +257,7 @@ Auto-compress MMS attachments Sinchronizuoti pranešimus Iš naujo sinchronizuoti Android pranešimų duomenų bazę - Apie Message + Apie QKSMS Versija %s Debug logging enabled Debug logging disabled @@ -333,6 +344,9 @@ Rodyti daugiau Rodyti mažiau Atidaryti pokalbį + „Material“ dizainas + HEX kodas + Pritaikyti None Archive @@ -353,6 +367,7 @@ Anuliuoti Nukopijuota Archyvuotas pokalbis + Reikia turėti QKSMS+ funkcijos naudojomui Naujas pranešimas %s nauji pranešimai @@ -386,12 +401,12 @@ Automatic - 100KB - 200KB - 300KB - 600KB - 1000KB - 2000KB + 100 kB + 200 kB + 300 kB + 600 kB + 1000 kB + 2000 kB No compression diff --git a/presentation/src/main/res/values-nb/strings.xml b/presentation/src/main/res/values-nb/strings.xml index 7ceb733ad07f8f656ba881cfb8dbcfcd2ad006b2..a7e0e67ee3c1170883db79d638a0b5f7863113e9 100644 --- a/presentation/src/main/res/values-nb/strings.xml +++ b/presentation/src/main/res/values-nb/strings.xml @@ -16,14 +16,16 @@ ~ ~ You should have received a copy of the GNU General Public License ~ along with QKSMS. If not, see . - --> + --> + Ny samtale Skriv Snarvei deaktivert Arkivert Innstillinger Varsler - Søk i innboks … + Drakt + Søk i innboks … Skriv navn eller nummer Hopp over Fortsett @@ -44,7 +46,7 @@ Mark read Mark unread Blokker - Synkroniserer meldinger… + Synkroniserer meldinger… Du: %s Draft Resultater i meldinger @@ -59,6 +61,7 @@ Tillatelse kreves QKSMS trenger tillatelse til å sende og vise tekstmeldinger QKSMS trenger tillatelse til å lese kontaktene dine + QKSMS needs permission to display notifications Tillat Innboks Arkivert @@ -68,6 +71,11 @@ Innstillinger Hjelp og tilbakemelding Inviter venner + Aktiver fantastiske nye funksjoner og støtt utviklingen + Liker du QKSMS? + Del litt kjærlighet og vurder oss på Google Play! + Ok! + Avvis Slett Er du sikker på at du vil slette samtalen? @@ -120,13 +128,14 @@ SIM %1$d (%2$s) selected %s er valgt, velg annet SIM-kort Send melding - Sender … + Sender … Levert %s Feil ved sending. Trykk for å prøve igjen Detaljer Address copied Tittel på samtalen Varsler + Drakt Arkiv Fjern fra arkiv Blokker @@ -137,30 +146,32 @@ Sikret Sikkerhetskopierer meldinger Gjenoppretter fra sikkerhetskopi - Siste sikkerhetskopi - Henter … + Henter … Aldri + Backup location + Set folder Gjenopprett Velg en sikkerhetskopi Vennligst aktiver QKSMS+ for å bruke sikkerhetskopiering og gjenoppretting - Sikkerhetskopiering pågår … - Gjenoppretting pågår … + Sikkerhetskopiering pågår … + Gjenoppretting pågår … Gjenopprett fra sikkerhetskopi - Er du sikker på at du vil gjenopprette meldinger fra denne sikkerhetskopien? Avbryt gjenoppretting Meldinger som allerede er gjenopprettet vil forbli på din enhet + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details Sikkerhetskopier Fant ingen sikkerhetskopier - - %d melding - %d meldinger - Per idag er bare mulig å sikkerhetskopiere SMS. MMS og planlagte sikkerhetskopier kommer snart. Sikkerhetskopier nå - Ser gjennom sikkerhetskopien … + Ser gjennom sikkerhetskopien … %d/%d meldinger - Lagrer sikkerhetskopi … - Synkroniserer meldinger … + Lagrer sikkerhetskopi … + Synkroniserer meldinger … Ferdig! Sikkerhetskopiering og gjenoppretting Planlagt @@ -180,6 +191,7 @@ Utseende Generelt Raskt svar + Drakt Nattmodus Ren svart nattmodus Starttid @@ -316,7 +328,7 @@ Svar på innkommende meldinger automatisk med et forhåndsdefinert svar Mer QKSMS er i stadig utvikling og ditt kjøp inkluderer alle fremtidige QKSMS+ funksjoner! - Laster inn … + Laster inn … Last inn flere samtaler Mark read Ring @@ -324,6 +336,9 @@ Vis mer Vis mindre Åpne samtale + Material + HEX + Bruk Ingen Archive @@ -398,5 +413,4 @@ LOL Det er greit - Melding - \ No newline at end of file + diff --git a/presentation/src/main/res/values-ne/strings.xml b/presentation/src/main/res/values-ne/strings.xml index 364ee8e92443683e1c7b02bbe46c39837b6c24c0..d0a8ca2f84e365b6af56602c1320a29a1fc896e4 100644 --- a/presentation/src/main/res/values-ne/strings.xml +++ b/presentation/src/main/res/values-ne/strings.xml @@ -24,6 +24,7 @@ Archived Settings Notifications + Theme Search inbox… Compose Skip @@ -55,11 +56,12 @@ Your archived conversations will appear here Start new conversation Love texting again - Make Message your default SMS app + Make QKSMS your default SMS app Change Permission required - Message needs permission to send and view SMS messages - Message needs permission to view your contacts + QKSMS needs permission to send and view SMS messages + QKSMS needs permission to view your contacts + QKSMS needs permission to display notifications Allow Inbox Archived @@ -69,6 +71,11 @@ Settings Help & feedback Invite friends + Unlock amazing new features, and support development + Enjoying QKSMS? + Share some love and rate us on Google Play! + OKAY! + DISMISS Delete Are you sure you would like to delete this conversation? @@ -91,6 +98,7 @@ Contact card Scheduled for Selected time must be in the future! + You must unlock QKSMS+ to use scheduled messaging Added to scheduled messages Write a message… Copy text @@ -127,6 +135,7 @@ Address copied Conversation title Notifications + Theme Archive Unarchive Block @@ -137,23 +146,26 @@ Backup and restore Backing up messages Restoring from backup - Last backup Loading… Never + Backup location + Set folder Restore Select a backup + Please unlock QKSMS+ to use backup and restore Backup in progress… Restore in progress… Restore from backup - Are you sure you would like to restore your messages from this backup? Stop restore Messages that have already been restored will remain on your device + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details Backups No backups found - - %d message - %d messages - Currently, only SMS is supported by Backup and Restore. MMS support and scheduled backups will be coming soon! Backup now Parsing backup… @@ -179,6 +191,7 @@ Appearance General QK Reply + Theme Night mode Pure black night mode Start time @@ -240,7 +253,7 @@ Auto-compress MMS attachments Sync messages Re-sync your messages with the native Android SMS database - About Message + About QKSMS Version %s Debug logging enabled Debug logging disabled @@ -323,6 +336,9 @@ Show more Show less Open conversation + Material + HEX + Apply None Archive @@ -343,6 +359,7 @@ Undo Copied Archived conversation + You must unlock QKSMS+ to use this New message %s new messages diff --git a/presentation/src/main/res/values-night-v23/themes.xml b/presentation/src/main/res/values-night-v23/themes.xml deleted file mode 100644 index 3adbc7c011078649b640b9a90ac4f4a3f522c016..0000000000000000000000000000000000000000 --- a/presentation/src/main/res/values-night-v23/themes.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - diff --git a/presentation/src/main/res/values-night/themes.xml b/presentation/src/main/res/values-night/themes.xml index f4ba0cb8117b0f3b709ab51156c64c3b010ea112..6d94faf5d1e9d8dbbed2b29beb4d105442efba49 100644 --- a/presentation/src/main/res/values-night/themes.xml +++ b/presentation/src/main/res/values-night/themes.xml @@ -19,7 +19,9 @@ --> - - - diff --git a/presentation/src/main/res/values-vi/strings.xml b/presentation/src/main/res/values-vi/strings.xml index 2c9450e0950230a3c7a7e176bdaa11861af7f371..a3a986212bc1c356763f8f1a959dfe4716cd000f 100644 --- a/presentation/src/main/res/values-vi/strings.xml +++ b/presentation/src/main/res/values-vi/strings.xml @@ -1,5 +1,4 @@ - 解锁并捐赠只需 %1$s %2$s - 感谢你对 Message 的支持! + 感谢你对 QKSMS 的支持! 现在你可以使用 QKSMS+ 的全部功能! 发生错误,请重试 QKSMS+ 对 F-Droid 用户免费!如果您想支持开发,可以随意捐款。 @@ -313,7 +323,7 @@ 自动回复 使用预设文本自动回复短信 更多 - Message 积极更新中,您的购买将包含未来 QKSMS+ 的所有功能! + QKSMS 积极更新中,您的购买将包含未来 QKSMS+ 的所有功能! 载入中... 查看更多对话 标记为已读 @@ -322,6 +332,9 @@ 显示更多 收起 打开会话 + Material + HEX + 应用 存档 @@ -342,6 +355,7 @@ 撤销 已复制 已存档的对话 + 您必须解锁 QKSMS+ 才能使用此功能 %s条新信息 diff --git a/presentation/src/main/res/values-zh/strings.xml b/presentation/src/main/res/values-zh/strings.xml index 48b2941cda7363e02fe42d0d5fb9034e881de083..7054b82467f935ef30ac8212da477c1cc2a76dc7 100644 --- a/presentation/src/main/res/values-zh/strings.xml +++ b/presentation/src/main/res/values-zh/strings.xml @@ -1,5 +1,4 @@ - + + Message + Make Message your default SMS app + Message needs permission to send and view SMS messages + Message needs permission to view your contacts + /Message/Backups + About Message + Message + Built-in blocking functionality in Message + Message is forked from QKSMS + Message Information + App Version + - Message is an open source replacement to the stock messaging app on Android. + Privacy policy + Terms of service + https://gitlab.e.foundation/e/apps/Message/-/blob/master/AUTHORS + Authors + Not able to add empty number ! please try again + Not able to add empty text ! please try again + diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 7351432965826f0769cf54e00b8ae5baca54b4a6..8f43fc9678c6d7585264104c9f5f3b9ee8208f7e 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -18,8 +18,8 @@ --> - Message - QKSMS+ + QKSMS + New conversation Compose Shortcut disabled @@ -30,6 +30,7 @@ Theme Search inbox… Type a name or number + QKSMS+ Skip Continue @@ -62,11 +63,12 @@ Your archived conversations will appear here Start new conversation Love texting again - Make Message your default SMS app + Make QKSMS your default SMS app Change Permission required - Message needs permission to send and view SMS messages - Message needs permission to view your contacts + QKSMS needs permission to send and view SMS messages + QKSMS needs permission to view your contacts + QKSMS needs permission to display notifications Allow Inbox @@ -78,6 +80,13 @@ QKSMS+ Help & feedback Invite friends + QKSMS+ + Unlock amazing new features, and support development + + Enjoying QKSMS? + Share some love and rate us on Google Play! + OKAY! + DISMISS Delete @@ -155,26 +164,27 @@ Backup and restore Backing up messages Restoring from backup - Last backup Loading… Never + Backup location + Set folder Restore Select a backup Please unlock QKSMS+ to use backup and restore Backup in progress… Restore in progress… Restore from backup - Are you sure you would like to restore your messages from this backup? Stop restore Messages that have already been restored will remain on your device + Select backup location + Please select a folder to save your backups to + %1$s\n%2$d messages + Error + Couldn\'t read backup file + Backup details Backups - /Message/Backups + /QKSMS/Backups No backups found - - No messages - %d message - %d messages - Currently, only SMS is supported by Backup and Restore. MMS support and scheduled backups will be coming soon! Backup now Parsing backup… @@ -266,7 +276,7 @@ Auto-compress MMS attachments Sync messages Re-sync your messages with the native Android SMS database - About Message + About QKSMS Version %s Debug logging enabled Debug logging disabled @@ -279,8 +289,8 @@ Blocked conversations Blocking Manager - Message - Built-in blocking functionality in Message + QKSMS + Built-in blocking functionality in QKSMS Call Blocker - Incoming/Outgoing Block spam messages, numbers & unknown calls with blacklist & Schedule Call Control @@ -313,23 +323,12 @@ About Version - Message is forked from QKSMS - Source code - License - Copyright - Developer + Source code Changelog Contact - - - - Message Information - App Version - - Message is an open source replacement to the stock messaging app on Android. - - Privacy policy - Terms of service + License + Copyright Support development, unlock everything You can save a starving developer for just %s @@ -382,11 +381,9 @@ HEX Apply - Moez Bhatti https://github.com/moezbhatti/qksms https://github.com/moezbhatti/qksms/releases - https://gitlab.e.foundation/e/apps/Message/-/blob/master/AUTHORS moez@qklabs.com GNU General Public License v3.0 © 2014–2019 @@ -398,7 +395,7 @@ Fixed More Dismiss - You must unlock QKSMS+ to use this + None Archive @@ -421,6 +418,7 @@ Copied Archived conversation + You must unlock QKSMS+ to use this New message @@ -457,7 +455,7 @@ - Automatic (uses allowed carrier max size) + Automatic 100KB 200KB 300KB @@ -493,18 +491,4 @@ That\'s okay - Authors - - - QKSMS+ - Unlock amazing new features, and support development - Enjoying Message? - Share some love and rate us on Google Play! - OKAY! - DISMISS - - Not able to add empty number ! please try again - - Not able to add empty text ! please try again - diff --git a/presentation/src/main/res/values/themes.xml b/presentation/src/main/res/values/themes.xml index b17e1435605a3f0cc29905bc3ef49adc22a376a3..1e38fd42d78593f016dbad5cd2341914f94a88fd 100644 --- a/presentation/src/main/res/values/themes.xml +++ b/presentation/src/main/res/values/themes.xml @@ -35,7 +35,10 @@ @style/customAlertDialog -