1
0
mirror of https://github.com/TwidereProject/Twidere-Android synced 2025-02-17 04:00:48 +01:00

added option to turn chrome custom tab off

This commit is contained in:
Mariotaku Lee 2017-01-11 16:52:54 +08:00
parent f9f058042b
commit 1b19806575
17 changed files with 419 additions and 225 deletions

View File

@ -0,0 +1,47 @@
package org.mariotaku.twidere.model;
import org.mariotaku.library.objectcursor.annotation.CursorField;
import org.mariotaku.library.objectcursor.annotation.CursorObject;
import org.mariotaku.twidere.provider.TwidereDataStore;
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
/**
* Created by mariotaku on 2017/1/9.
*/
@CursorObject(valuesCreator = true, tableInfo = true)
public class FiltersSubscription {
@CursorField(value = Filters.Subscriptions._ID, excludeWrite = true, type = TwidereDataStore.TYPE_PRIMARY_KEY)
public long id;
@CursorField(Filters.Subscriptions.COMPONENT)
public String component;
@CursorField(Filters.Subscriptions.ARGUMENTS)
public String arguments;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FiltersSubscription that = (FiltersSubscription) o;
return id == that.id;
}
@Override
public int hashCode() {
return (int) (id ^ (id >>> 32));
}
@Override
public String toString() {
return "FiltersSubscription{" +
"arguments='" + arguments + '\'' +
", id=" + id +
", component='" + component + '\'' +
'}';
}
}

View File

@ -26,6 +26,7 @@ import android.provider.BaseColumns;
import org.mariotaku.twidere.model.DraftTableInfo;
import org.mariotaku.twidere.model.FiltersData$BaseItemTableInfo;
import org.mariotaku.twidere.model.FiltersData$UserItemTableInfo;
import org.mariotaku.twidere.model.FiltersSubscriptionTableInfo;
import org.mariotaku.twidere.model.ParcelableActivityTableInfo;
import org.mariotaku.twidere.model.ParcelableDirectMessageTableInfo;
import org.mariotaku.twidere.model.ParcelableStatusTableInfo;
@ -621,6 +622,21 @@ public interface TwidereDataStore {
String[] TYPES = FiltersData$UserItemTableInfo.TYPES;
}
interface Subscriptions extends BaseColumns {
String TABLE_NAME = "filters_subscriptions";
String CONTENT_PATH_SEGMENT = "subscriptions";
String CONTENT_PATH = Filters.CONTENT_PATH + "/" + CONTENT_PATH_SEGMENT;
Uri CONTENT_URI = Uri.withAppendedPath(Filters.CONTENT_URI, CONTENT_PATH_SEGMENT);
String COMPONENT = "component";
String ARGUMENTS = "arguments";
String[] COLUMNS = FiltersSubscriptionTableInfo.COLUMNS;
String[] TYPES = FiltersSubscriptionTableInfo.TYPES;
}
}
interface Mentions extends Statuses {
@ -964,6 +980,7 @@ public interface TwidereDataStore {
String DEFAULT_SORT_ORDER = POSITION + " ASC";
}
interface CachedRelationships extends BaseColumns, AccountSupportColumns {
String TABLE_NAME = "cached_relationships";

View File

@ -0,0 +1,9 @@
package org.mariotaku.twidere.util.filter;
/**
* Created by mariotaku on 2017/1/9.
*/
public interface FiltersSubscriptionProvider {
}

View File

@ -42,7 +42,6 @@ class GooglePlayInAppPurchaseActivity : AbsExtraFeaturePurchaseActivity(),
super.onDestroy()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (!billingProcessor.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data)
@ -127,7 +126,7 @@ class GooglePlayInAppPurchaseActivity : AbsExtraFeaturePurchaseActivity(),
BILLING_RESPONSE_RESULT_USER_CANCELED -> Activity.RESULT_CANCELED
BILLING_RESPONSE_RESULT_SERVICE_UNAVAILABLE -> RESULT_SERVICE_UNAVAILABLE
BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED -> RESULT_NOT_PURCHASED
BILLING_RESPONSE_RESULT_ERROR -> RESULT_NOT_PURCHASED
BILLING_RESPONSE_RESULT_ERROR -> RESULT_INTERNAL_ERROR
else -> billingResponse
}
return resultCode
@ -138,6 +137,5 @@ class GooglePlayInAppPurchaseActivity : AbsExtraFeaturePurchaseActivity(),
companion object {
private const val TAG_PURCHASE_PROCESS = "get_purchase_process"
const val EXTRA_PRODUCT_ID = "product_id"
}
}

View File

@ -0,0 +1,91 @@
package org.mariotaku.twidere.util.sync.dropbox
import android.content.Context
import com.dropbox.core.DbxException
import com.dropbox.core.v2.DbxClientV2
import com.dropbox.core.v2.files.DeleteArg
import com.dropbox.core.v2.files.FileMetadata
import com.dropbox.core.v2.files.ListFolderErrorException
import com.dropbox.core.v2.files.ListFolderResult
import org.mariotaku.twidere.extension.model.filename
import org.mariotaku.twidere.extension.model.readMimeMessageFrom
import org.mariotaku.twidere.extension.model.writeMimeMessageTo
import org.mariotaku.twidere.model.Draft
import org.mariotaku.twidere.util.sync.FileBasedDraftsSyncAction
import java.io.IOException
import java.util.*
class DropboxDraftsSyncAction(context: Context, val client: DbxClientV2) : FileBasedDraftsSyncAction<FileMetadata>(context) {
@Throws(IOException::class)
override fun Draft.saveToRemote(): FileMetadata {
try {
client.newUploader("/Drafts/$filename", this.timestamp).use {
this.writeMimeMessageTo(context, it.outputStream)
return it.finish()
}
} catch (e: DbxException) {
throw IOException(e)
}
}
@Throws(IOException::class)
override fun Draft.loadFromRemote(info: FileMetadata): Boolean {
try {
client.files().download(info.pathLower).use {
val parsed = this.readMimeMessageFrom(context, it.inputStream)
if (parsed) {
this.timestamp = info.draftTimestamp
this.unique_id = info.draftFileName.substringBeforeLast(".eml")
}
return parsed
}
} catch (e: DbxException) {
throw IOException(e)
}
}
@Throws(IOException::class)
override fun removeDrafts(list: List<FileMetadata>): Boolean {
try {
return client.files().deleteBatch(list.map { DeleteArg(it.pathLower) }) != null
} catch (e: DbxException) {
throw IOException(e)
}
}
@Throws(IOException::class)
override fun removeDraft(info: FileMetadata): Boolean {
try {
return client.files().delete(info.pathLower) != null
} catch (e: DbxException) {
throw IOException(e)
}
}
override val FileMetadata.draftTimestamp: Long get() = this.clientModified.time
override val FileMetadata.draftFileName: String get() = this.name
@Throws(IOException::class)
override fun listRemoteDrafts(): List<FileMetadata> {
val result = ArrayList<FileMetadata>()
try {
var listResult: ListFolderResult = client.files().listFolder("/Drafts/")
while (true) {
// Do something with files
listResult.entries.mapNotNullTo(result) { it as? FileMetadata }
if (!listResult.hasMore) break
listResult = client.files().listFolderContinue(listResult.cursor)
}
} catch (e: DbxException) {
if (e is ListFolderErrorException) {
if (e.errorValue?.pathValue?.isNotFound ?: false) {
return emptyList()
}
}
throw IOException(e)
}
return result
}
}

View File

@ -0,0 +1,53 @@
package org.mariotaku.twidere.util.sync.dropbox
import android.content.Context
import com.dropbox.core.DbxDownloader
import com.dropbox.core.v2.DbxClientV2
import com.dropbox.core.v2.files.FileMetadata
import com.dropbox.core.v2.files.UploadUploader
import org.mariotaku.twidere.extension.model.initFields
import org.mariotaku.twidere.extension.model.parse
import org.mariotaku.twidere.extension.model.serialize
import org.mariotaku.twidere.extension.newPullParser
import org.mariotaku.twidere.extension.newSerializer
import org.mariotaku.twidere.model.FiltersData
import org.mariotaku.twidere.util.sync.FileBasedFiltersDataSyncAction
internal class DropboxFiltersDataSyncAction(
context: Context,
val client: DbxClientV2
) : FileBasedFiltersDataSyncAction<DbxDownloader<FileMetadata>, DropboxUploadSession<FiltersData>>(context) {
override fun DbxDownloader<FileMetadata>.getRemoteLastModified(): Long {
return result.clientModified.time
}
private val filePath = "/Common/filters.xml"
override fun newLoadFromRemoteSession(): DbxDownloader<FileMetadata> {
return client.newDownloader(filePath)
}
override fun DbxDownloader<FileMetadata>.loadFromRemote(): FiltersData {
val data = FiltersData()
data.parse(inputStream.newPullParser(charset = Charsets.UTF_8))
data.initFields()
return data
}
override fun DropboxUploadSession<FiltersData>.setRemoteLastModified(lastModified: Long) {
this.localModifiedTime = lastModified
}
override fun DropboxUploadSession<FiltersData>.saveToRemote(data: FiltersData): Boolean {
return this.uploadData(data)
}
override fun newSaveToRemoteSession(): DropboxUploadSession<FiltersData> {
return object : DropboxUploadSession<FiltersData>(filePath, client) {
override fun performUpload(uploader: UploadUploader, data: FiltersData) {
data.serialize(uploader.outputStream.newSerializer(charset = Charsets.UTF_8, indent = true))
}
}
}
}

View File

@ -0,0 +1,52 @@
package org.mariotaku.twidere.util.sync.dropbox
import android.content.Context
import android.content.SharedPreferences
import com.dropbox.core.DbxDownloader
import com.dropbox.core.v2.DbxClientV2
import com.dropbox.core.v2.files.FileMetadata
import com.dropbox.core.v2.files.UploadUploader
import org.mariotaku.twidere.extension.newPullParser
import org.mariotaku.twidere.extension.newSerializer
import org.mariotaku.twidere.util.sync.FileBasedPreferencesValuesSyncAction
import java.util.*
internal class DropboxPreferencesValuesSyncAction(
context: Context,
val client: DbxClientV2,
preferences: SharedPreferences,
processor: Processor,
val filePath: String
) : FileBasedPreferencesValuesSyncAction<DbxDownloader<FileMetadata>,
DropboxUploadSession<Map<String, String>>>(context, preferences, processor) {
override fun DbxDownloader<FileMetadata>.getRemoteLastModified(): Long {
return result.clientModified.time
}
override fun DbxDownloader<FileMetadata>.loadFromRemote(): MutableMap<String, String> {
val data = HashMap<String, String>()
data.parse(inputStream.newPullParser())
return data
}
override fun newLoadFromRemoteSession(): DbxDownloader<FileMetadata> {
return client.newDownloader(filePath)
}
override fun newSaveToRemoteSession(): DropboxUploadSession<Map<String, String>> {
return object : DropboxUploadSession<Map<String, String>>(filePath, client) {
override fun performUpload(uploader: UploadUploader, data: Map<String, String>) {
data.serialize(uploader.outputStream.newSerializer(charset = Charsets.UTF_8,
indent = true))
}
}
}
override fun DropboxUploadSession<Map<String, String>>.saveToRemote(data: MutableMap<String, String>): Boolean {
return this.uploadData(data)
}
override fun DropboxUploadSession<Map<String, String>>.setRemoteLastModified(lastModified: Long) {
this.localModifiedTime = lastModified
}
}

View File

@ -0,0 +1,40 @@
package org.mariotaku.twidere.util.sync.dropbox
import com.dropbox.core.DbxDownloader
import com.dropbox.core.DbxException
import com.dropbox.core.v2.DbxClientV2
import com.dropbox.core.v2.files.DownloadErrorException
import com.dropbox.core.v2.files.FileMetadata
import com.dropbox.core.v2.files.UploadUploader
import com.dropbox.core.v2.files.WriteMode
import java.io.FileNotFoundException
import java.io.IOException
import java.util.*
/**
* Created by mariotaku on 2017/1/10.
*/
@Throws(IOException::class)
internal fun DbxClientV2.newUploader(path: String, clientModified: Long): UploadUploader {
try {
return files().uploadBuilder(path).withMode(WriteMode.OVERWRITE).withMute(true)
.withClientModified(Date(clientModified)).start()
} catch (e: DbxException) {
throw IOException(e)
}
}
@Throws(IOException::class)
internal fun DbxClientV2.newDownloader(path: String): DbxDownloader<FileMetadata> {
try {
return files().downloadBuilder(path).start()
} catch (e: DownloadErrorException) {
if (e.errorValue?.pathValue?.isNotFound ?: false) {
throw FileNotFoundException(path)
}
throw IOException(e)
} catch (e: DbxException) {
throw IOException(e)
}
}

View File

@ -1,27 +1,17 @@
package org.mariotaku.twidere.util.sync.dropbox;
import android.content.Context
import android.content.SharedPreferences
import com.dropbox.core.DbxDownloader
import com.dropbox.core.DbxException
import com.dropbox.core.DbxRequestConfig
import com.dropbox.core.v2.DbxClientV2
import com.dropbox.core.v2.files.*
import nl.komponents.kovenant.task
import nl.komponents.kovenant.ui.failUi
import nl.komponents.kovenant.ui.successUi
import org.mariotaku.twidere.BuildConfig
import org.mariotaku.twidere.extension.model.*
import org.mariotaku.twidere.extension.newPullParser
import org.mariotaku.twidere.extension.newSerializer
import org.mariotaku.twidere.model.Draft
import org.mariotaku.twidere.model.FiltersData
import org.mariotaku.twidere.util.TaskServiceRunner
import org.mariotaku.twidere.util.sync.*
import java.io.Closeable
import java.io.FileNotFoundException
import java.io.IOException
import java.util.*
import org.mariotaku.twidere.util.sync.ISyncAction
import org.mariotaku.twidere.util.sync.SyncTaskRunner
import org.mariotaku.twidere.util.sync.UserColorsSyncProcessor
import org.mariotaku.twidere.util.sync.UserNicknamesSyncProcessor
/**
* Created by mariotaku on 2017/1/6.
@ -54,209 +44,4 @@ class DropboxSyncTaskRunner(context: Context, val authToken: String) : SyncTaskR
return true
}
class DropboxDraftsSyncAction(context: Context, val client: DbxClientV2) : FileBasedDraftsSyncAction<FileMetadata>(context) {
@Throws(IOException::class)
override fun Draft.saveToRemote(): FileMetadata {
try {
client.newUploader("/Drafts/$filename", this.timestamp).use {
this.writeMimeMessageTo(context, it.outputStream)
return it.finish()
}
} catch (e: DbxException) {
throw IOException(e)
}
}
@Throws(IOException::class)
override fun Draft.loadFromRemote(info: FileMetadata): Boolean {
try {
client.files().download(info.pathLower).use {
val parsed = this.readMimeMessageFrom(context, it.inputStream)
if (parsed) {
this.timestamp = info.draftTimestamp
this.unique_id = info.draftFileName.substringBeforeLast(".eml")
}
return parsed
}
} catch (e: DbxException) {
throw IOException(e)
}
}
@Throws(IOException::class)
override fun removeDrafts(list: List<FileMetadata>): Boolean {
try {
return client.files().deleteBatch(list.map { DeleteArg(it.pathLower) }) != null
} catch (e: DbxException) {
throw IOException(e)
}
}
@Throws(IOException::class)
override fun removeDraft(info: FileMetadata): Boolean {
try {
return client.files().delete(info.pathLower) != null
} catch (e: DbxException) {
throw IOException(e)
}
}
override val FileMetadata.draftTimestamp: Long get() = this.clientModified.time
override val FileMetadata.draftFileName: String get() = this.name
@Throws(IOException::class)
override fun listRemoteDrafts(): List<FileMetadata> {
val result = ArrayList<FileMetadata>()
try {
var listResult: ListFolderResult = client.files().listFolder("/Drafts/")
while (true) {
// Do something with files
listResult.entries.mapNotNullTo(result) { it as? FileMetadata }
if (!listResult.hasMore) break
listResult = client.files().listFolderContinue(listResult.cursor)
}
} catch (e: DbxException) {
if (e is ListFolderErrorException) {
if (e.errorValue?.pathValue?.isNotFound ?: false) {
return emptyList()
}
}
throw IOException(e)
}
return result
}
}
internal class DropboxFiltersDataSyncAction(
context: Context,
val client: DbxClientV2
) : FileBasedFiltersDataSyncAction<DbxDownloader<FileMetadata>, DropboxUploadSession<FiltersData>>(context) {
override fun DbxDownloader<FileMetadata>.getRemoteLastModified(): Long {
return result.clientModified.time
}
private val filePath = "/Common/filters.xml"
override fun newLoadFromRemoteSession(): DbxDownloader<FileMetadata> {
return client.newDownloader(filePath)
}
override fun DbxDownloader<FileMetadata>.loadFromRemote(): FiltersData {
val data = FiltersData()
data.parse(inputStream.newPullParser(charset = Charsets.UTF_8))
data.initFields()
return data
}
override fun DropboxUploadSession<FiltersData>.setRemoteLastModified(lastModified: Long) {
this.localModifiedTime = lastModified
}
override fun DropboxUploadSession<FiltersData>.saveToRemote(data: FiltersData): Boolean {
return this.uploadData(data)
}
override fun newSaveToRemoteSession(): DropboxUploadSession<FiltersData> {
return object : DropboxUploadSession<FiltersData>(filePath, client) {
override fun performUpload(uploader: UploadUploader, data: FiltersData) {
data.serialize(uploader.outputStream.newSerializer(charset = Charsets.UTF_8, indent = true))
}
}
}
}
internal class DropboxPreferencesValuesSyncAction(
context: Context,
val client: DbxClientV2,
preferences: SharedPreferences,
processor: Processor,
val filePath: String
) : FileBasedPreferencesValuesSyncAction<DbxDownloader<FileMetadata>,
DropboxUploadSession<Map<String, String>>>(context, preferences, processor) {
override fun DbxDownloader<FileMetadata>.getRemoteLastModified(): Long {
return result.clientModified.time
}
override fun DbxDownloader<FileMetadata>.loadFromRemote(): MutableMap<String, String> {
val data = HashMap<String, String>()
data.parse(inputStream.newPullParser())
return data
}
override fun newLoadFromRemoteSession(): DbxDownloader<FileMetadata> {
return client.newDownloader(filePath)
}
override fun newSaveToRemoteSession(): DropboxUploadSession<Map<String, String>> {
return object : DropboxUploadSession<Map<String, String>>(filePath, client) {
override fun performUpload(uploader: UploadUploader, data: Map<String, String>) {
data.serialize(uploader.outputStream.newSerializer(charset = Charsets.UTF_8,
indent = true))
}
}
}
override fun DropboxUploadSession<Map<String, String>>.saveToRemote(data: MutableMap<String, String>): Boolean {
return this.uploadData(data)
}
override fun DropboxUploadSession<Map<String, String>>.setRemoteLastModified(lastModified: Long) {
this.localModifiedTime = lastModified
}
}
abstract internal class DropboxUploadSession<in Data>(val fileName: String, val client: DbxClientV2) : Closeable {
private var uploader: UploadUploader? = null
var localModifiedTime: Long = 0
override fun close() {
uploader?.close()
}
@Throws(IOException::class)
abstract fun performUpload(uploader: UploadUploader, data: Data)
fun uploadData(data: Data): Boolean {
uploader = client.newUploader(fileName, localModifiedTime).apply {
performUpload(this, data)
this.finish()
}
return true
}
}
companion object {
@Throws(IOException::class)
private fun DbxClientV2.newUploader(path: String, clientModified: Long): UploadUploader {
try {
return files().uploadBuilder(path).withMode(WriteMode.OVERWRITE).withMute(true)
.withClientModified(Date(clientModified)).start()
} catch (e: DbxException) {
throw IOException(e)
}
}
@Throws(IOException::class)
private fun DbxClientV2.newDownloader(path: String): DbxDownloader<FileMetadata> {
try {
return files().downloadBuilder(path).start()
} catch (e: DownloadErrorException) {
if (e.errorValue?.pathValue?.isNotFound ?: false) {
throw FileNotFoundException(path)
}
throw IOException(e)
} catch (e: DbxException) {
throw IOException(e)
}
}
}
}

View File

@ -0,0 +1,28 @@
package org.mariotaku.twidere.util.sync.dropbox
import com.dropbox.core.v2.DbxClientV2
import com.dropbox.core.v2.files.UploadUploader
import java.io.Closeable
import java.io.IOException
abstract internal class DropboxUploadSession<in Data>(val fileName: String, val client: DbxClientV2) : Closeable {
private var uploader: UploadUploader? = null
var localModifiedTime: Long = 0
override fun close() {
uploader?.close()
}
@Throws(IOException::class)
abstract fun performUpload(uploader: UploadUploader, data: Data)
fun uploadData(data: Data): Boolean {
uploader = client.newUploader(fileName, localModifiedTime).apply {
performUpload(this, data)
this.finish()
}
return true
}
}

View File

@ -58,7 +58,7 @@ val themeKey = KStringKey(KEY_THEME, VALUE_THEME_NAME_LIGHT)
val themeColorKey = KIntKey(KEY_THEME_COLOR, 0)
val filterUnavailableQuoteStatusesKey = KBooleanKey("filter_unavailable_quote_statuses", false)
val filterPossibilitySensitiveStatusesKey = KBooleanKey("filter_possibility_sensitive_statuses", false)
val chromeCustomTabKey = KBooleanKey("chrome_custom_tab", true)
object themeBackgroundAlphaKey : KSimpleKey<Int>(KEY_THEME_BACKGROUND_ALPHA, 0xFF) {
override fun read(preferences: SharedPreferences): Int {
return preferences.getInt(KEY_THEME_BACKGROUND_ALPHA, DEFAULT_THEME_BACKGROUND_ALPHA)

View File

@ -0,0 +1,19 @@
package org.mariotaku.twidere.extension.model
import android.content.Context
import org.mariotaku.twidere.model.FiltersSubscription
import org.mariotaku.twidere.util.filter.FiltersSubscriptionProvider
import org.mariotaku.twidere.util.filter.LocalFiltersSubscriptionProvider
/**
* Created by mariotaku on 2017/1/9.
*/
fun FiltersSubscription.instantiateComponent(context: Context): FiltersSubscriptionProvider? {
val component = this.component ?: return null
if (component.startsWith(":")) {
// Load builtin service
return LocalFiltersSubscriptionProvider.forName(context, component.substringAfter(":"))
}
return null
}

View File

@ -36,6 +36,7 @@ import org.mariotaku.twidere.activity.WebLinkHandlerActivity
import org.mariotaku.twidere.annotation.Referral
import org.mariotaku.twidere.app.TwidereApplication
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT_KEY
import org.mariotaku.twidere.constant.chromeCustomTabKey
import org.mariotaku.twidere.constant.newDocumentApiKey
import org.mariotaku.twidere.model.UserKey
import org.mariotaku.twidere.model.util.ParcelableMediaUtils
@ -161,15 +162,26 @@ open class OnLinkClickHandler(
protected open fun openLink(link: String) {
if (manager != null && manager.isActive) return
val uri = Uri.parse(link)
if (!preferences[chromeCustomTabKey]) {
val viewIntent = Intent(Intent.ACTION_VIEW, uri)
viewIntent.addCategory(Intent.CATEGORY_BROWSABLE)
try {
return context.startActivity(viewIntent)
} catch (e: ActivityNotFoundException) {
// Ignore
}
return
}
val builder = CustomTabsIntent.Builder()
(ChameleonUtils.getActivity(context) as? Chameleon.Themeable)?.overrideTheme?.let { theme ->
builder.setToolbarColor(theme.colorToolbar)
}
val intent = builder.build()
try {
intent.launchUrl(context, Uri.parse(link))
intent.launchUrl(context, uri)
} catch (e: ActivityNotFoundException) {
// TODO
// Ignore
}
}

View File

@ -0,0 +1,20 @@
package org.mariotaku.twidere.util.filter
import android.content.Context
/**
* Created by mariotaku on 2017/1/9.
*/
abstract class LocalFiltersSubscriptionProvider(val context: Context) : FiltersSubscriptionProvider {
companion object {
fun forName(context: Context, name: String): FiltersSubscriptionProvider? {
when (name) {
"url" -> {
return UrlFiltersSubscriptionProvider(context)
}
}
return null
}
}
}

View File

@ -0,0 +1,15 @@
package org.mariotaku.twidere.util.filter;
import android.content.Context;
import org.jetbrains.annotations.NotNull;
/**
* Created by mariotaku on 2017/1/9.
*/
public class UrlFiltersSubscriptionProvider extends LocalFiltersSubscriptionProvider {
public UrlFiltersSubscriptionProvider(@NotNull Context context) {
super(context);
}
}

View File

@ -894,4 +894,6 @@
<string name="message_sync_disconnect_from_name_confirm">Disconnect from <xliff:g example="ownCloud" id="name">%s</xliff:g>?</string>
<string name="message_sync_last_synced_time">Last synced: <xliff:g example="2017/1/1 12:00" id="time">%s</xliff:g></string>
<string name="action_purchase_features_pack">Buy features pack</string>
<string name="preference_title_chrome_custom_tab">Chrome custom tab</string>
<string name="preference_summary_chrome_custom_tab">Open links in Chrome custom tab</string>
</resources>

View File

@ -71,6 +71,12 @@
android:summary="@string/preference_multitasking_summary"
android:title="@string/preference_multitasking"/>
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="chrome_custom_tab"
android:summary="@string/preference_summary_chrome_custom_tab"
android:title="@string/preference_title_chrome_custom_tab"/>
</PreferenceCategory>
<PreferenceCategory