fixed an NPE after cleaning database

removed nickname_only option
rewrote notifications
This commit is contained in:
Mariotaku Lee 2015-03-24 23:40:47 +08:00
parent 44752e47c7
commit 2a071975bc
71 changed files with 1313 additions and 1914 deletions

View File

@ -220,16 +220,6 @@ public interface SharedPreferenceConstants {
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = true)
public static final String KEY_NAME_FIRST = "name_first";
public static final String KEY_STOP_AUTO_REFRESH_WHEN_BATTERY_LOW = "stop_auto_refresh_when_battery_low";
@Preference(type = BOOLEAN, exportable = false)
public static final String KEY_UCD_DATA_PROFILING = "ucd_data_profiling";
@Preference(type = BOOLEAN, exportable = false)
public static final String KEY_SPICE_DATA_PROFILING = "spice_data_profiling";
@Preference(type = STRING, exportable = false)
public static final String KEY_SPICE_DEVICE_ID = "spice_device_id";
@Preference(type = BOOLEAN, exportable = false)
public static final String KEY_SHOW_UCD_DATA_PROFILING_REQUEST = "show_ucd_data_profiling_request";
@Preference(type = BOOLEAN, exportable = false)
public static final String KEY_SHOW_SPICE_DATA_PROFILING_REQUEST = "show_spice_data_profiling_request";
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false)
public static final String KEY_DISPLAY_SENSITIVE_CONTENTS = "display_sensitive_contents";
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = true)
@ -268,8 +258,6 @@ public interface SharedPreferenceConstants {
public static final String KEY_FILTERS_IN_HOME_TIMELINE = "filters_in_home_timeline";
public static final String KEY_FILTERS_IN_MENTIONS_TIMELINE = "filters_in_mentions";
public static final String KEY_FILTERS_FOR_RTS = "filters_for_rts";
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false)
public static final String KEY_NICKNAME_ONLY = "nickname_only";
public static final String KEY_SETTINGS_WIZARD_COMPLETED = "settings_wizard_completed";
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = true)
public static final String KEY_CARD_ANIMATION = "card_animation";

View File

@ -70,6 +70,10 @@ public class Expression implements SQLLang {
return new Expression(String.format(Locale.ROOT, "%s = %d", l, r));
}
public static Expression greaterThan(final String l, final long r) {
return new Expression(String.format(Locale.ROOT, "%s > %d", l, r));
}
public static Expression in(final Column column, final Selectable in) {
return new Expression(String.format("%s IN(%s)", column.getSQL(), in.getSQL()));
}

View File

@ -1,96 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mariotaku.twidere"
xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
>
android:installLocation="auto" >
<uses-sdk/>
<uses-sdk />
<uses-feature
android:name="android.hardware.camera"
android:required="false"/>
android:required="false" />
<uses-feature
android:name="android.hardware.location"
android:required="false"/>
android:required="false" />
<uses-feature
android:name="android.hardware.location.gps"
android:required="false"/>
android:required="false" />
<uses-feature
android:name="android.hardware.location.network"
android:required="false"/>
android:required="false" />
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false"/>
android:required="false" />
<uses-feature
android:name="android.hardware.nfc"
android:required="false"/>
android:required="false" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
android:required="true" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.NFC"/>
<uses-permission android:name="org.mariotaku.twidere.permission.SHORTEN_STATUS"/>
<uses-permission android:name="org.mariotaku.twidere.permission.UPLOAD_MEDIA"/>
<uses-permission android:name="org.mariotaku.twidere.permission.SYNC_TIMELINE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="org.mariotaku.twidere.permission.SHORTEN_STATUS" />
<uses-permission android:name="org.mariotaku.twidere.permission.UPLOAD_MEDIA" />
<uses-permission android:name="org.mariotaku.twidere.permission.SYNC_TIMELINE" />
<permission-group
android:name="org.mariotaku.twidere.permission.PERMISSION_GROUP"
android:label="@string/app_name"/>
android:label="@string/app_name" />
<permission
android:description="@string/permission_description_shorten_status"
android:name="org.mariotaku.twidere.permission.SHORTEN_STATUS"
android:permissionGroup="org.mariotaku.twidere.permission.PERMISSION_GROUP"/>
android:description="@string/permission_description_shorten_status"
android:permissionGroup="org.mariotaku.twidere.permission.PERMISSION_GROUP" />
<permission
android:description="@string/permission_description_upload_media"
android:name="org.mariotaku.twidere.permission.UPLOAD_MEDIA"
android:permissionGroup="org.mariotaku.twidere.permission.PERMISSION_GROUP"/>
android:description="@string/permission_description_upload_media"
android:permissionGroup="org.mariotaku.twidere.permission.PERMISSION_GROUP" />
<permission
android:description="@string/permission_description_sync_timeline"
android:name="org.mariotaku.twidere.permission.SYNC_TIMELINE"
android:permissionGroup="org.mariotaku.twidere.permission.PERMISSION_GROUP"/>
android:description="@string/permission_description_sync_timeline"
android:permissionGroup="org.mariotaku.twidere.permission.PERMISSION_GROUP" />
<application
android:name=".app.TwidereApplication"
android:allowBackup="true"
android:backupAgent="org.mariotaku.twidere.backup.TwidereBackupAgentHelper"
android:backupAgent=".backup.TwidereBackupAgentHelper"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.Blank">
android:theme="@style/Theme.Blank" >
<uses-library
android:name="com.sec.android.app.multiwindow"
android:required="false"/>
android:required="false" />
<meta-data
android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAIKbKATV1AGbLB4kem3w8QaPVJSPVVumbMHxkfwA"/>
android:value="AEdPqrEAAAAIKbKATV1AGbLB4kem3w8QaPVJSPVVumbMHxkfwA" />
<meta-data
android:name="com.sec.android.support.multiwindow"
android:value="true"/>
android:value="true" />
<meta-data
android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W"
android:value="480dp"/>
android:value="480dp" />
<meta-data
android:name="com.sec.android.multiwindow.DEFAULT_SIZE_H"
android:value="640dp"/>
android:value="640dp" />
<meta-data
android:name="com.sec.android.multiwindow.MINIMUM_SIZE_W"
android:value="240dp"/>
android:value="240dp" />
<meta-data
android:name="com.sec.android.multiwindow.MINIMUM_SIZE_H"
android:value="320dp"/>
android:value="320dp" />
<meta-data
android:name="override_tinted_status_bar_defaults"
android:value="true"/>
android:value="true" />
<activity
android:name=".activity.MainActivity"
@ -98,13 +96,13 @@
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/Theme.Launcher"
android:windowSoftInputMode="adjustNothing">
android:windowSoftInputMode="adjustNothing" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
@ -114,37 +112,37 @@
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/Theme.Launcher"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER"/>
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.MULTIWINDOW_LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.support.HomeActivity"
android:label="@string/app_name"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="org.mariotaku.twidere.HOME"/>
<action android:name="org.mariotaku.twidere.HOME" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEARCH"/>
<action android:name="android.intent.action.SEARCH" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.app.searchable"
android:resource="@xml/searchable"/>
android:resource="@xml/searchable" />
<meta-data
android:name="android.app.default_searchable"
android:value=".activity.support.HomeActivity"/>
android:value=".activity.support.HomeActivity" />
</activity>
<activity
android:name=".activity.support.ComposeActivity"
@ -152,245 +150,246 @@
android:label="@string/compose"
android:launchMode="singleTop"
android:theme="@style/Theme.Blank.Dialog"
android:windowSoftInputMode="adjustResize">
<intent-filter android:label="@string/compose">
<action android:name="android.intent.action.MAIN"/>
<action android:name="org.mariotaku.twidere.COMPOSE"/>
<action android:name="org.mariotaku.twidere.REPLY"/>
<action android:name="org.mariotaku.twidere.QUOTE"/>
<action android:name="org.mariotaku.twidere.EDIT_DRAFT"/>
<action android:name="org.mariotaku.twidere.MENTION"/>
<action android:name="org.mariotaku.twidere.REPLY_MULTIPLE"/>
android:windowSoftInputMode="adjustResize" >
<intent-filter android:label="@string/compose" >
<action android:name="android.intent.action.MAIN" />
<action android:name="org.mariotaku.twidere.COMPOSE" />
<action android:name="org.mariotaku.twidere.REPLY" />
<action android:name="org.mariotaku.twidere.QUOTE" />
<action android:name="org.mariotaku.twidere.EDIT_DRAFT" />
<action android:name="org.mariotaku.twidere.MENTION" />
<action android:name="org.mariotaku.twidere.REPLY_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.SEND"/>
<action android:name="android.intent.action.SEND_MULTIPLE"/>
<intent-filter android:label="@string/app_name" >
<action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*"/>
<data android:mimeType="text/plain"/>
<data android:mimeType="image/*" />
<data android:mimeType="text/plain" />
</intent-filter>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.support.HomeActivity"/>
android:value=".activity.support.HomeActivity" />
</activity>
<activity
android:name=".activity.support.QuickSearchBarActivity"
android:label="@android:string/search_go"
android:launchMode="singleTop"
android:theme="@style/Theme.Blank.Dialog"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="org.mariotaku.twidere.GLOBAL_SEARCH"/>
<category android:name="android.intent.category.DEFAULT"/>
<action android:name="org.mariotaku.twidere.GLOBAL_SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.support.SignInActivity"
android:label="@string/sign_in"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="org.mariotaku.twidere.TWITTER_LOGIN"/>
<action android:name="org.mariotaku.twidere.TWITTER_LOGIN" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.support.BrowserSignInActivity"
android:label="@string/browser_sign_in"
android:theme="@style/Theme.Blank.Dialog"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="org.mariotaku.twidere.TWITTER_BROWSER_LOGIN"/>
<action android:name="org.mariotaku.twidere.TWITTER_BROWSER_LOGIN" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.SettingsActivity"
android:label="@string/settings"
android:theme="@style/Theme.Blank"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MANAGE_NETWORK_USAGE"/>
<action android:name="org.mariotaku.twidere.SETTINGS"/>
<action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
<action android:name="org.mariotaku.twidere.SETTINGS" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.support.HomeActivity"/>
android:value=".activity.support.HomeActivity" />
</activity>
<activity
android:name=".activity.FiltersActivity"
android:label="@string/filters">
android:label="@string/filters" >
<intent-filter>
<action android:name="org.mariotaku.twidere.FILTERS"/>
<action android:name="org.mariotaku.twidere.FILTERS" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.support.HomeActivity"/>
android:value=".activity.support.HomeActivity" />
</activity>
<activity
android:name=".activity.support.APIEditorActivity"
android:label="@string/edit_api"
android:theme="@style/Theme.Blank.Dialog"
android:windowSoftInputMode="adjustResize"/>
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".activity.support.AccountSelectorActivity"
android:label="@string/select_account"
android:theme="@style/Theme.Blank.Dialog">
android:theme="@style/Theme.Blank.Dialog" >
<intent-filter>
<action android:name="org.mariotaku.twidere.SELECT_ACCOUNT"/>
<action android:name="org.mariotaku.twidere.SELECT_ACCOUNT" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.support.BrowserActivity"
android:exported="false"
android:label="@string/browser">
android:label="@string/browser" >
<intent-filter>
<action android:name="org.mariotaku.twidere.VIEW_WEBPAGE"/>
<action android:name="org.mariotaku.twidere.VIEW_WEBPAGE" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file"/>
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:scheme="file" />
<data android:scheme="http" />
<data android:scheme="https" />
</intent-filter>
</activity>
<activity
android:name=".activity.support.ColorPickerDialogActivity"
android:label="@string/set_color"
android:theme="@style/Theme.Twidere.Light.NoDisplay"/>
android:theme="@style/Theme.Twidere.Light.NoDisplay" />
<activity
android:name=".activity.support.LinkHandlerActivity"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.support.HomeActivity"/>
android:value=".activity.support.HomeActivity" />
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="user"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="users"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_timeline"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_media_timeline"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_favorites"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_followers"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_friends"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_blocks"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="status"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="status_retweeters"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="status_favoriters"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="status_replies"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="statuses"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="direct_messages_conversation"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_list"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_lists"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_list_timeline"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_list_members"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_list_subscribers"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_list_memberships"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="saved_searches"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="user_mentions"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="incoming_friendships"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="search"
android:scheme="twidere"/>
android:scheme="twidere" />
<data
android:host="mutes_users"
android:scheme="twidere"/>
android:scheme="twidere" />
</intent-filter>
</activity>
<activity
android:name=".activity.support.DraftsActivity"
android:exported="false"
android:label="@string/drafts"
android:launchMode="singleTop">
android:launchMode="singleTop" >
<intent-filter>
<action android:name="org.mariotaku.twidere.DRAFTS"/>
<action android:name="org.mariotaku.twidere.DRAFTS" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.support.HomeActivity"/>
android:value=".activity.support.HomeActivity" />
</activity>
<activity
android:name=".activity.support.AccountsManagerActivity"
android:exported="false"
android:label="@string/accounts"
android:launchMode="singleTop">
android:launchMode="singleTop" >
<intent-filter>
<action android:name="org.mariotaku.twidere.ACCOUNTS"/>
<action android:name="org.mariotaku.twidere.ACCOUNTS" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.support.HomeActivity"/>
android:value=".activity.support.HomeActivity" />
</activity>
<activity
android:name=".activity.support.MediaViewerActivity"
@ -398,16 +397,16 @@
android:hardwareAccelerated="true"
android:label="@string/media"
android:launchMode="singleTop"
android:theme="@style/Theme.Twidere.Viewer">
android:theme="@style/Theme.Twidere.Viewer" >
<intent-filter>
<action android:name="org.mariotaku.twidere.VIEW_MEDIA"/>
<action android:name="org.mariotaku.twidere.VIEW_MEDIA" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"/>
<data android:scheme="https"/>
<data android:scheme="file"/>
<data android:scheme="http" />
<data android:scheme="https" />
<data android:scheme="file" />
</intent-filter>
</activity>
<activity
@ -415,255 +414,255 @@
android:exported="false"
android:label="@string/pick_file"
android:theme="@style/Theme.Twidere.Light.NoDisplay"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="org.mariotaku.twidere.PICK_FILE"/>
<action android:name="org.mariotaku.twidere.PICK_DIRECTORY"/>
<action android:name="org.mariotaku.twidere.PICK_FILE" />
<action android:name="org.mariotaku.twidere.PICK_DIRECTORY" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.support.ImagePickerActivity"
android:exported="false"
android:theme="@style/Theme.Twidere.Light.NoDisplay"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="org.mariotaku.twidere.PICK_IMAGE"/>
<action android:name="org.mariotaku.twidere.TAKE_PHOTO"/>
<action android:name="android.intent.action.MAIN" />
<action android:name="org.mariotaku.twidere.PICK_IMAGE" />
<action android:name="org.mariotaku.twidere.TAKE_PHOTO" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.support.UserProfileEditorActivity"
android:exported="false"
android:label="@string/edit_profile"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="org.mariotaku.twidere.EDIT_USER_PROFILE"/>
<action android:name="org.mariotaku.twidere.EDIT_USER_PROFILE" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.CustomTabsActivity"
android:label="@string/tabs"
android:theme="@style/Theme.Blank"/>
android:theme="@style/Theme.Blank" />
<activity
android:name=".activity.support.CustomTabEditorActivity"
android:exported="false"
android:label="@string/add_tab"
android:theme="@style/Theme.Blank.Dialog"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="org.mariotaku.twidere.ADD_TAB"/>
<action android:name="org.mariotaku.twidere.EDIT_TAB"/>
<action android:name="org.mariotaku.twidere.ADD_TAB" />
<action android:name="org.mariotaku.twidere.EDIT_TAB" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.CreateComposeShortcutActivity"
android:label="@string/compose"
android:theme="@style/Theme.Twidere.Dark.NoDisplay">
android:theme="@style/Theme.Twidere.Dark.NoDisplay" >
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT"/>
<action android:name="android.intent.action.CREATE_SHORTCUT" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.DataProfilingSettingsActivity"
android:exported="false"
android:label="@string/data_profiling"
android:theme="@style/Theme.Blank"/>
<activity
android:name=".activity.support.RequestPermissionsActivity"
android:label="@string/permissions_request"
android:theme="@style/Theme.Blank.Dialog">
android:theme="@style/Theme.Blank.Dialog" >
<intent-filter>
<action android:name="org.mariotaku.twidere.REQUEST_PERMISSIONS"/>
<action android:name="org.mariotaku.twidere.REQUEST_PERMISSIONS" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.CameraCropActivity"
android:exported="false">
android:exported="false" >
<intent-filter>
<action android:name="org.mariotaku.twidere.CAMERA_CROP"/>
<action android:name="org.mariotaku.twidere.CAMERA_CROP" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.support.UserListSelectorActivity"
android:label="@string/select_user_list"
android:theme="@style/Theme.Blank.Dialog">
android:theme="@style/Theme.Blank.Dialog" >
<intent-filter>
<action android:name="org.mariotaku.twidere.SELECT_USER"/>
<action android:name="org.mariotaku.twidere.SELECT_USER_LIST"/>
<action android:name="org.mariotaku.twidere.SELECT_USER" />
<action android:name="org.mariotaku.twidere.SELECT_USER_LIST" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.SettingsWizardActivity"
android:label="@string/settings_wizard"
android:theme="@style/Theme.Twidere.Wizard"/>
android:theme="@style/Theme.Twidere.Wizard" />
<activity
android:name=".activity.support.DataExportActivity"
android:label="@string/export_settings"
android:theme="@android:style/Theme.NoDisplay"/>
android:theme="@android:style/Theme.NoDisplay" />
<activity
android:name=".activity.support.DataImportActivity"
android:label="@string/import_settings"
android:theme="@android:style/Theme.NoDisplay"/>
android:theme="@android:style/Theme.NoDisplay" />
<activity
android:name=".activity.support.ActivityPickerActivity"
android:theme="@style/Theme.Blank.Dialog">
android:theme="@style/Theme.Blank.Dialog" >
<intent-filter>
<action android:name="org.mariotaku.twidere.PICK_ACTIVITY"/>
<action android:name="org.mariotaku.twidere.PICK_ACTIVITY" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".activity.TwitterLinkHandlerActivity"
android:excludeFromRecents="true"
android:taskAffinity=":twidere_twitter_link_handler"
android:theme="@style/Theme.Launcher">
android:theme="@style/Theme.Launcher" >
<intent-filter>
<data
android:host="twitter.com"
android:scheme="http"/>
android:scheme="http" />
<data
android:host="twitter.com"
android:scheme="https"/>
android:scheme="https" />
<data
android:host="www.twitter.com"
android:scheme="http"/>
android:scheme="http" />
<data
android:host="www.twitter.com"
android:scheme="https"/>
android:scheme="https" />
<data
android:host="mobile.twitter.com"
android:scheme="http"/>
android:scheme="http" />
<data
android:host="mobile.twitter.com"
android:scheme="https"/>
android:scheme="https" />
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
<activity
android:name=".activity.AssistLauncherActivity"
android:excludeFromRecents="true"
android:taskAffinity=":twidere_assist_launcher"
android:theme="@style/Theme.Launcher">
android:theme="@style/Theme.Launcher" >
<intent-filter>
<action android:name="android.intent.action.ASSIST"/>
<action android:name="android.intent.action.ASSIST" />
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data
android:name="com.android.systemui.action_assist_icon"
android:resource="@drawable/ic_assist_twidere"/>
android:resource="@drawable/ic_assist_twidere" />
</activity>
<activity
android:name=".activity.TestActivity"
android:enabled="false"
android:launchMode="singleTop"
android:label="Twidere test"
android:windowSoftInputMode="adjustResize">
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activity.NyanActivity"
android:launchMode="singleTop"
android:theme="@style/Theme.Nyan"
android:windowSoftInputMode="stateAlwaysHidden"/>
android:windowSoftInputMode="stateAlwaysHidden" />
<activity
android:name=".activity.support.UsageStatisticsActivity"
android:label="@string/title_activity_usage_statistics" >
</activity>
<service
android:name=".service.RefreshService"
android:label="@string/label_refresh_service"
android:settingsActivity=".activity.SettingsActivity"/>
android:settingsActivity=".activity.SettingsActivity" />
<service
android:name=".service.BackgroundOperationService"
android:label="@string/label_background_operation_service"/>
android:label="@string/label_background_operation_service" />
<service
android:name="edu.ucdavis.earlybird.UCDService"
android:settingsActivity=".activity.DataProfilingSettingsActivity"/>
<!--SPICE-->
android:settingsActivity=".activity.support.UsageStatisticsActivity" />
<!-- SPICE -->
<service
android:name="edu.tsinghua.spice.SpiceService"
android:settingsActivity=".activity.DataProfilingSettingsActivity"/>
android:settingsActivity=".activity.support.UsageStatisticsActivity" />
<service
android:name=".service.DashClockHomeUnreadCountService"
android:icon="@drawable/ic_extension_twidere"
android:label="@string/dashclock_home_unread_count_name"
android:permission="com.google.android.apps.dashclock.permission.READ_EXTENSION_DATA">
android:permission="com.google.android.apps.dashclock.permission.READ_EXTENSION_DATA" >
<intent-filter>
<action android:name="com.google.android.apps.dashclock.Extension"/>
<action android:name="com.google.android.apps.dashclock.Extension" />
</intent-filter>
<meta-data
android:name="protocolVersion"
android:value="2"/>
android:value="2" />
<meta-data
android:name="worldReadable"
android:value="true"/>
android:value="true" />
<meta-data
android:name="description"
android:value="@string/dashclock_home_unread_count_description"/>
android:value="@string/dashclock_home_unread_count_description" />
</service>
<service
android:name=".service.DashClockMentionsUnreadCountService"
android:icon="@drawable/ic_extension_mentions"
android:label="@string/dashclock_mentions_unread_count_name"
android:permission="com.google.android.apps.dashclock.permission.READ_EXTENSION_DATA">
android:permission="com.google.android.apps.dashclock.permission.READ_EXTENSION_DATA" >
<intent-filter>
<action android:name="com.google.android.apps.dashclock.Extension"/>
<action android:name="com.google.android.apps.dashclock.Extension" />
</intent-filter>
<meta-data
android:name="protocolVersion"
android:value="2"/>
android:value="2" />
<meta-data
android:name="worldReadable"
android:value="true"/>
android:value="true" />
<meta-data
android:name="description"
android:value="@string/dashclock_mentions_unread_count_description"/>
android:value="@string/dashclock_mentions_unread_count_description" />
</service>
<service
android:name=".service.DashClockMessagesUnreadCountService"
android:icon="@drawable/ic_extension_messages"
android:label="@string/dashclock_messages_unread_count_name"
android:permission="com.google.android.apps.dashclock.permission.READ_EXTENSION_DATA">
android:permission="com.google.android.apps.dashclock.permission.READ_EXTENSION_DATA" >
<intent-filter>
<action android:name="com.google.android.apps.dashclock.Extension"/>
<action android:name="com.google.android.apps.dashclock.Extension" />
</intent-filter>
<meta-data
android:name="protocolVersion"
android:value="2"/>
android:value="2" />
<meta-data
android:name="worldReadable"
android:value="true"/>
android:value="true" />
<meta-data
android:name="description"
android:value="@string/dashclock_messages_unread_count_description"/>
android:value="@string/dashclock_messages_unread_count_description" />
</service>
<service
android:name=".nyan.NyanWallpaperService"
@ -672,14 +671,14 @@
android:icon="@drawable/nyan_sakamoto_thumbnail"
android:label="@string/nyan_sakamoto"
android:permission="android.permission.BIND_WALLPAPER"
android:process=":wallpaper">
<intent-filter android:priority="1">
<action android:name="android.service.wallpaper.WallpaperService"/>
android:process=":wallpaper" >
<intent-filter android:priority="1" >
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data
android:name="android.service.wallpaper"
android:resource="@xml/nyan_wallpaper"/>
android:resource="@xml/nyan_wallpaper" />
</service>
<service
android:name=".nyan.NyanDaydreamService"
@ -687,9 +686,9 @@
android:exported="true"
android:icon="@drawable/nyan_sakamoto_thumbnail"
android:label="@string/nyan_sakamoto"
android:process=":daydream">
<intent-filter android:priority="1">
<action android:name="android.service.dreams.DreamService"/>
android:process=":daydream" >
<intent-filter android:priority="1" >
<action android:name="android.service.dreams.DreamService" />
</intent-filter>
</service>
@ -698,52 +697,53 @@
android:authorities="twidere"
android:exported="true"
android:grantUriPermissions="true"
android:label="@string/label_tweetstore_provider"/>
android:label="@string/label_tweetstore_provider" />
<provider
android:name=".provider.TwidereCommandProvider"
android:authorities="twidere.command"
android:exported="true"/>
android:exported="true" />
<provider
android:name=".provider.RecentSearchProvider"
android:authorities="org.mariotaku.twidere.provider.SearchRecentSuggestions"/>
android:authorities="org.mariotaku.twidere.provider.SearchRecentSuggestions" />
<receiver android:name=".receiver.ConnectivityStateReceiver">
<receiver android:name=".receiver.ConnectivityStateReceiver" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
<receiver
android:name=".receiver.SecretCodeBroadcastReceiver"
android:label="@string/twidere_test">
android:label="@string/twidere_test" >
<intent-filter>
<action android:name="android.provider.Telephony.SECRET_CODE"/>
<action android:name="android.provider.Telephony.SECRET_CODE" />
<data
android:host="8943373"
android:scheme="android_secret_code"/>
android:scheme="android_secret_code" />
</intent-filter>
</receiver>
<receiver
android:name="edu.ucdavis.earlybird.UploadReceiver"
android:exported="false">
android:exported="false" >
<intent-filter>
<action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE"/>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
<action android:name="edu.ucdavis.earlybird.UPLOAD_PROFILE"/>
<action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
<action android:name="edu.ucdavis.earlybird.UPLOAD_PROFILE" />
</intent-filter>
</receiver>
<!--SPICE-->
<!-- SPICE -->
<receiver
android:name="edu.tsinghua.spice.SpiceUploadReceiver"
android:exported="false">
android:exported="false" >
<intent-filter>
<action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE"/>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
<action android:name="edu.tsinghua.spice.UPLOAD_PROFILE"/>
<action android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
<action android:name="edu.tsinghua.spice.UPLOAD_PROFILE" />
</intent-filter>
</receiver>
</application>
</manifest>
</manifest>

View File

@ -0,0 +1,45 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package android.support.v7.widget;
import android.content.Context;
import android.view.View;
/**
* Created by mariotaku on 15/3/24.
*/
public class FixedLinearLayoutManager extends LinearLayoutManager {
public FixedLinearLayoutManager(Context context) {
super(context);
}
public FixedLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
View findOneVisibleChild(int fromIndex, int toIndex, boolean completelyVisible, boolean acceptPartiallyVisible) {
// XXX Fixed NPE by add a simple check to child view count
if (getChildCount() < 0) return null;
return super.findOneVisibleChild(fromIndex, toIndex, completelyVisible, acceptPartiallyVisible);
}
}

View File

@ -3,16 +3,20 @@ package edu.tsinghua.spice.Task;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.util.Log;
import org.mariotaku.twidere.util.Utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import edu.tsinghua.spice.Utilies.SpiceHttpUtil;
import edu.tsinghua.spice.Utilies.SpiceIOUtil;
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
import twitter4j.http.HttpClientWrapper;
import twitter4j.http.HttpParameter;
import static org.mariotaku.twidere.TwidereConstants.LOGTAG;
import static org.mariotaku.twidere.util.Utils.copyStream;
/**
@ -26,20 +30,19 @@ public class SpiceAsyUploadTask extends AsyncTask<Void, Void, Void> {
private static final String LAST_UPLOAD_DATE = "last_upload_time";
private static final double MILLSECS_HALF_DAY = 1000 * 60 * 60 * 12;
//private final String device_id;
private final Context context;
private final HttpClientWrapper client;
private SpiceHttpUtil uploadClient;
// private SpiceHttpUtil uploadClient;
public SpiceAsyUploadTask(final Context context) {
this.context = context;
// device_id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
this.client = Utils.getDefaultHttpClient(context);
}
public void uploadMultipart(SpiceHttpUtil client, final File file) {
public void uploadMultipart(final File file) {
String fileName = file.getName();
final String app_root = file.getParent();
final File tmp_dir = new File(app_root + "/spice");
if (!tmp_dir.exists()) {
@ -53,22 +56,16 @@ public class SpiceAsyUploadTask extends AsyncTask<Void, Void, Void> {
file.renameTo(tmp);
try {
client.connectForMultipart();
client.addFilePart("file", fileName, SpiceIOUtil.readFile(tmp));
client.finishMultipart();
String serverResponseCode = client.getResponse();
if (serverResponseCode.contains("00")) {
SpiceProfilingUtil.log(context, "server has already received file " + tmp.getName());
tmp.delete();
} else {
SpiceProfilingUtil.log(context, "server does not receive file " + tmp.getName());
putBackProfile(context, tmp, file);
}
final String url = PROFILE_SERVER_URL;
final HttpParameter[] parameters = {new HttpParameter("file", tmp)};
client.post(url, url, parameters);
SpiceProfilingUtil.log(context, "server has already received file " + tmp.getName());
tmp.delete();
} catch (Exception e) {
e.printStackTrace();
if (Utils.isDebugBuild()) {
Log.w(LOGTAG, e);
SpiceProfilingUtil.log(context, "server does not receive file " + tmp.getName());
}
putBackProfile(context, tmp, file);
}
@ -104,8 +101,7 @@ public class SpiceAsyUploadTask extends AsyncTask<Void, Void, Void> {
}
final String url = PROFILE_SERVER_URL;
SpiceProfilingUtil.log(context, url);
uploadClient = new SpiceHttpUtil(url);
uploadMultipart(uploadClient, file);
uploadMultipart(file);
}
return false;
}

View File

@ -19,6 +19,11 @@
package org.mariotaku.twidere;
import org.mariotaku.twidere.annotation.Preference;
import static org.mariotaku.twidere.annotation.Preference.Type.BOOLEAN;
import static org.mariotaku.twidere.annotation.Preference.Type.STRING;
/**
* Constants requires full application to build or useless for other
* applications
@ -27,155 +32,162 @@ package org.mariotaku.twidere;
*/
public interface Constants extends TwidereConstants {
public static final String DATABASES_NAME = "twidere.sqlite";
public static final int DATABASES_VERSION = 87;
String DATABASES_NAME = "twidere.sqlite";
int DATABASES_VERSION = 87;
public static final int MENU_GROUP_STATUS_EXTENSION = 10;
public static final int MENU_GROUP_COMPOSE_EXTENSION = 11;
public static final int MENU_GROUP_IMAGE_EXTENSION = 12;
public static final int MENU_GROUP_USER_EXTENSION = 13;
public static final int MENU_GROUP_USER_LIST_EXTENSION = 14;
public static final int MENU_GROUP_STATUS_SHARE = 20;
int MENU_GROUP_STATUS_EXTENSION = 10;
int MENU_GROUP_COMPOSE_EXTENSION = 11;
int MENU_GROUP_IMAGE_EXTENSION = 12;
int MENU_GROUP_USER_EXTENSION = 13;
int MENU_GROUP_USER_LIST_EXTENSION = 14;
int MENU_GROUP_STATUS_SHARE = 20;
public static final int MENU_HOME = android.R.id.home;
public static final int MENU_SEARCH = R.id.search;
public static final int MENU_ACTIONS = R.id.actions;
public static final int MENU_COMPOSE = R.id.compose;
public static final int MENU_SEND = R.id.send;
public static final int MENU_EDIT = R.id.edit;
public static final int MENU_SELECT_ACCOUNT = R.id.select_account;
public static final int MENU_SETTINGS = R.id.settings;
public static final int MENU_ADD_LOCATION = R.id.add_location;
public static final int MENU_TAKE_PHOTO = R.id.take_photo;
public static final int MENU_ADD_IMAGE = R.id.add_image;
public static final int MENU_LOCATION = R.id.location;
public static final int MENU_IMAGE = R.id.image;
public static final int MENU_VIEW = R.id.view;
public static final int MENU_VIEW_PROFILE = R.id.view_profile;
public static final int MENU_DELETE = R.id.delete;
public static final int MENU_DELETE_SUBMENU = R.id.delete_submenu;
public static final int MENU_TOGGLE = R.id.toggle;
public static final int MENU_ADD = R.id.add;
public static final int MENU_PICK_FROM_GALLERY = R.id.pick_from_gallery;
public static final int MENU_PICK_FROM_MAP = R.id.pick_from_map;
public static final int MENU_EDIT_API = R.id.edit_api;
public static final int MENU_OPEN_IN_BROWSER = R.id.open_in_browser;
public static final int MENU_SET_COLOR = R.id.set_color;
public static final int MENU_ADD_ACCOUNT = R.id.add_account;
public static final int MENU_REPLY = R.id.reply;
public static final int MENU_FAVORITE = R.id.favorite;
public static final int MENU_RETWEET = R.id.retweet;
public static final int MENU_QUOTE = R.id.quote;
public static final int MENU_SHARE = R.id.share;
public static final int MENU_DRAFTS = R.id.drafts;
public static final int MENU_DELETE_ALL = R.id.delete_all;
public static final int MENU_SET_AS_DEFAULT = R.id.set_as_default;
public static final int MENU_SAVE = R.id.save;
public static final int MENU_CANCEL = R.id.cancel;
public static final int MENU_BLOCK = R.id.block;
public static final int MENU_REPORT_SPAM = R.id.report_spam;
public static final int MENU_MUTE_SOURCE = R.id.mute_source;
public static final int MENU_MUTE_USER = R.id.mute_user;
public static final int MENU_REFRESH = R.id.refresh;
public static final int MENU_MENTION = R.id.mention;
public static final int MENU_SEND_DIRECT_MESSAGE = R.id.send_direct_message;
public static final int MENU_VIEW_USER_LIST = R.id.view_user_list;
public static final int MENU_UP = R.id.up;
public static final int MENU_DOWN = R.id.down;
public static final int MENU_COPY = R.id.copy;
public static final int MENU_TOGGLE_SENSITIVE = R.id.toggle_sensitive;
public static final int MENU_REVOKE = R.id.revoke;
public static final int MENU_ADD_TO_LIST = R.id.add_to_list;
public static final int MENU_DELETE_FROM_LIST = R.id.delete_from_list;
public static final int MENU_STATUSES = R.id.statuses;
public static final int MENU_FAVORITES = R.id.favorites;
public static final int MENU_LISTS = R.id.lists;
public static final int MENU_LIST_MEMBERSHIPS = R.id.list_memberships;
public static final int MENU_CENTER = R.id.center;
public static final int MENU_FILTERS = R.id.filters;
public static final int MENU_SET_NICKNAME = R.id.set_nickname;
public static final int MENU_CLEAR_NICKNAME = R.id.clear_nickname;
public static final int MENU_ADD_TO_FILTER = R.id.add_to_filter;
public static final int MENU_FOLLOW = R.id.follow;
public static final int MENU_UNFOLLOW = R.id.unfollow;
public static final int MENU_BACK = R.id.back;
public static final int MENU_TRANSLATE = R.id.translate;
public static final int MENU_ACCEPT = R.id.accept;
public static final int MENU_DENY = R.id.deny;
public static final int MENU_IMPORT_SETTINGS = R.id.import_settings;
public static final int MENU_EXPORT_SETTINGS = R.id.export_settings;
public static final int MENU_PROGRESS = R.id.progress;
public static final int MENU_OPEN_WITH_ACCOUNT = R.id.open_with_account;
public static final int MENU_ACCOUNTS = R.id.accounts;
public static final int MENU_INVERSE_SELECTION = R.id.inverse_selection;
public static final int MENU_EDIT_MEDIA = R.id.edit_media;
int MENU_HOME = android.R.id.home;
int MENU_SEARCH = R.id.search;
int MENU_ACTIONS = R.id.actions;
int MENU_COMPOSE = R.id.compose;
int MENU_SEND = R.id.send;
int MENU_EDIT = R.id.edit;
int MENU_SELECT_ACCOUNT = R.id.select_account;
int MENU_SETTINGS = R.id.settings;
int MENU_ADD_LOCATION = R.id.add_location;
int MENU_TAKE_PHOTO = R.id.take_photo;
int MENU_ADD_IMAGE = R.id.add_image;
int MENU_LOCATION = R.id.location;
int MENU_IMAGE = R.id.image;
int MENU_VIEW = R.id.view;
int MENU_VIEW_PROFILE = R.id.view_profile;
int MENU_DELETE = R.id.delete;
int MENU_DELETE_SUBMENU = R.id.delete_submenu;
int MENU_TOGGLE = R.id.toggle;
int MENU_ADD = R.id.add;
int MENU_PICK_FROM_GALLERY = R.id.pick_from_gallery;
int MENU_PICK_FROM_MAP = R.id.pick_from_map;
int MENU_EDIT_API = R.id.edit_api;
int MENU_OPEN_IN_BROWSER = R.id.open_in_browser;
int MENU_SET_COLOR = R.id.set_color;
int MENU_ADD_ACCOUNT = R.id.add_account;
int MENU_REPLY = R.id.reply;
int MENU_FAVORITE = R.id.favorite;
int MENU_RETWEET = R.id.retweet;
int MENU_QUOTE = R.id.quote;
int MENU_SHARE = R.id.share;
int MENU_DRAFTS = R.id.drafts;
int MENU_DELETE_ALL = R.id.delete_all;
int MENU_SET_AS_DEFAULT = R.id.set_as_default;
int MENU_SAVE = R.id.save;
int MENU_CANCEL = R.id.cancel;
int MENU_BLOCK = R.id.block;
int MENU_REPORT_SPAM = R.id.report_spam;
int MENU_MUTE_SOURCE = R.id.mute_source;
int MENU_MUTE_USER = R.id.mute_user;
int MENU_REFRESH = R.id.refresh;
int MENU_MENTION = R.id.mention;
int MENU_SEND_DIRECT_MESSAGE = R.id.send_direct_message;
int MENU_VIEW_USER_LIST = R.id.view_user_list;
int MENU_UP = R.id.up;
int MENU_DOWN = R.id.down;
int MENU_COPY = R.id.copy;
int MENU_TOGGLE_SENSITIVE = R.id.toggle_sensitive;
int MENU_REVOKE = R.id.revoke;
int MENU_ADD_TO_LIST = R.id.add_to_list;
int MENU_DELETE_FROM_LIST = R.id.delete_from_list;
int MENU_STATUSES = R.id.statuses;
int MENU_FAVORITES = R.id.favorites;
int MENU_LISTS = R.id.lists;
int MENU_LIST_MEMBERSHIPS = R.id.list_memberships;
int MENU_CENTER = R.id.center;
int MENU_FILTERS = R.id.filters;
int MENU_SET_NICKNAME = R.id.set_nickname;
int MENU_CLEAR_NICKNAME = R.id.clear_nickname;
int MENU_ADD_TO_FILTER = R.id.add_to_filter;
int MENU_FOLLOW = R.id.follow;
int MENU_UNFOLLOW = R.id.unfollow;
int MENU_BACK = R.id.back;
int MENU_TRANSLATE = R.id.translate;
int MENU_ACCEPT = R.id.accept;
int MENU_DENY = R.id.deny;
int MENU_IMPORT_SETTINGS = R.id.import_settings;
int MENU_EXPORT_SETTINGS = R.id.export_settings;
int MENU_PROGRESS = R.id.progress;
int MENU_OPEN_WITH_ACCOUNT = R.id.open_with_account;
int MENU_ACCOUNTS = R.id.accounts;
int MENU_INVERSE_SELECTION = R.id.inverse_selection;
int MENU_EDIT_MEDIA = R.id.edit_media;
public static final int LINK_ID_STATUS = 1;
public static final int LINK_ID_USER = 2;
public static final int LINK_ID_USER_TIMELINE = 3;
public static final int LINK_ID_USER_FAVORITES = 4;
public static final int LINK_ID_USER_FOLLOWERS = 5;
public static final int LINK_ID_USER_FRIENDS = 6;
public static final int LINK_ID_USER_BLOCKS = 7;
public static final int LINK_ID_USER_MEDIA_TIMELINE = 8;
public static final int LINK_ID_DIRECT_MESSAGES_CONVERSATION = 9;
public static final int LINK_ID_USER_LIST = 10;
public static final int LINK_ID_USER_LISTS = 11;
public static final int LINK_ID_USER_LIST_TIMELINE = 12;
public static final int LINK_ID_USER_LIST_MEMBERS = 13;
public static final int LINK_ID_USER_LIST_SUBSCRIBERS = 14;
public static final int LINK_ID_USER_LIST_MEMBERSHIPS = 15;
public static final int LINK_ID_SAVED_SEARCHES = 19;
public static final int LINK_ID_USER_MENTIONS = 21;
public static final int LINK_ID_INCOMING_FRIENDSHIPS = 22;
public static final int LINK_ID_USERS = 23;
public static final int LINK_ID_STATUSES = 24;
public static final int LINK_ID_STATUS_RETWEETERS = 25;
public static final int LINK_ID_STATUS_REPLIES = 26;
public static final int LINK_ID_STATUS_FAVORITERS = 27;
public static final int LINK_ID_SEARCH = 28;
public static final int LINK_ID_MUTES_USERS = 41;
int LINK_ID_STATUS = 1;
int LINK_ID_USER = 2;
int LINK_ID_USER_TIMELINE = 3;
int LINK_ID_USER_FAVORITES = 4;
int LINK_ID_USER_FOLLOWERS = 5;
int LINK_ID_USER_FRIENDS = 6;
int LINK_ID_USER_BLOCKS = 7;
int LINK_ID_USER_MEDIA_TIMELINE = 8;
int LINK_ID_DIRECT_MESSAGES_CONVERSATION = 9;
int LINK_ID_USER_LIST = 10;
int LINK_ID_USER_LISTS = 11;
int LINK_ID_USER_LIST_TIMELINE = 12;
int LINK_ID_USER_LIST_MEMBERS = 13;
int LINK_ID_USER_LIST_SUBSCRIBERS = 14;
int LINK_ID_USER_LIST_MEMBERSHIPS = 15;
int LINK_ID_SAVED_SEARCHES = 19;
int LINK_ID_USER_MENTIONS = 21;
int LINK_ID_INCOMING_FRIENDSHIPS = 22;
int LINK_ID_USERS = 23;
int LINK_ID_STATUSES = 24;
int LINK_ID_STATUS_RETWEETERS = 25;
int LINK_ID_STATUS_REPLIES = 26;
int LINK_ID_STATUS_FAVORITERS = 27;
int LINK_ID_SEARCH = 28;
int LINK_ID_MUTES_USERS = 41;
public static final String DIR_NAME_IMAGE_CACHE = "image_cache";
public static final String DIR_NAME_FULL_IMAGE_CACHE = "full_image_cache";
String DIR_NAME_IMAGE_CACHE = "image_cache";
String DIR_NAME_FULL_IMAGE_CACHE = "full_image_cache";
public static final String FRAGMENT_TAG_API_UPGRADE_NOTICE = "api_upgrade_notice";
String FRAGMENT_TAG_API_UPGRADE_NOTICE = "api_upgrade_notice";
public static final String TWIDERE_PREVIEW_NICKNAME = "Twidere";
public static final String TWIDERE_PREVIEW_NAME = "Twidere Project";
public static final String TWIDERE_PREVIEW_SCREEN_NAME = "TwidereProject";
public static final String TWIDERE_PREVIEW_TEXT_HTML = "Twidere is an open source twitter client for Android, see <a href='https://github.com/mariotaku/twidere'>github.com/mariotak&#8230;<a/>";
public static final String TWIDERE_PREVIEW_SOURCE = "Twidere for Android";
String TWIDERE_PREVIEW_NICKNAME = "Twidere";
String TWIDERE_PREVIEW_NAME = "Twidere Project";
String TWIDERE_PREVIEW_SCREEN_NAME = "TwidereProject";
String TWIDERE_PREVIEW_TEXT_HTML = "Twidere is an open source twitter client for Android, see <a href='https://github.com/mariotaku/twidere'>github.com/mariotak&#8230;<a/>";
String TWIDERE_PREVIEW_SOURCE = "Twidere for Android";
public static final long HONDAJOJO_ID = 514378421;
public static final String HONDAJOJO_SCREEN_NAME = "HondaJOJO";
public static final int UUCKY_ID = 1062473329;
public static final String UUCKY_SCREEN_NAME = "Uucky_Lee";
public static final String EASTER_EGG_TRIGGER_TEXT = "\u718A\u5B69\u5B50";
public static final String EASTER_EGG_RESTORE_TEXT_PART1 = "\u5927\u738B";
public static final String EASTER_EGG_RESTORE_TEXT_PART2 = "\u5C0F\u7684";
public static final String EASTER_EGG_RESTORE_TEXT_PART3 = "\u77E5\u9519";
long HONDAJOJO_ID = 514378421;
String HONDAJOJO_SCREEN_NAME = "HondaJOJO";
int UUCKY_ID = 1062473329;
String UUCKY_SCREEN_NAME = "Uucky_Lee";
String EASTER_EGG_TRIGGER_TEXT = "\u718A\u5B69\u5B50";
String EASTER_EGG_RESTORE_TEXT_PART1 = "\u5927\u738B";
String EASTER_EGG_RESTORE_TEXT_PART2 = "\u5C0F\u7684";
String EASTER_EGG_RESTORE_TEXT_PART3 = "\u77E5\u9519";
public static final float DEFAULT_PULL_TO_REFRESH_SCROLL_DISTANCE = 0.3f;
float DEFAULT_PULL_TO_REFRESH_SCROLL_DISTANCE = 0.3f;
public static final String ENTRY_PREFERENCES = "preferences.json";
public static final String ENTRY_NICKNAMES = "nicknames.json";
public static final String ENTRY_USER_COLORS = "user_colors.json";
public static final String ENTRY_HOST_MAPPING = "host_mapping.json";
String ENTRY_PREFERENCES = "preferences.json";
String ENTRY_NICKNAMES = "nicknames.json";
String ENTRY_USER_COLORS = "user_colors.json";
String ENTRY_HOST_MAPPING = "host_mapping.json";
public static final int FLAG_PREFERENCES = 0x1;
public static final int FLAG_NICKNAMES = 0x2;
public static final int FLAG_USER_COLORS = 0x4;
public static final int FLAG_HOST_MAPPING = 0x8;
int FLAG_PREFERENCES = 0x1;
int FLAG_NICKNAMES = 0x2;
int FLAG_USER_COLORS = 0x4;
int FLAG_HOST_MAPPING = 0x8;
public static final int FLAG_ALL = FLAG_PREFERENCES | FLAG_NICKNAMES | FLAG_USER_COLORS | FLAG_HOST_MAPPING;
int FLAG_ALL = FLAG_PREFERENCES | FLAG_NICKNAMES | FLAG_USER_COLORS | FLAG_HOST_MAPPING;
public static final int[] PRESET_COLORS = {R.color.material_red, R.color.material_pink,
int[] PRESET_COLORS = {R.color.material_red, R.color.material_pink,
R.color.material_purple, R.color.material_deep_purple, R.color.material_indigo,
R.color.material_blue, R.color.material_light_blue, R.color.material_cyan,
R.color.material_teal, R.color.material_green, R.color.material_light_green,
R.color.material_lime, R.color.material_yellow, R.color.material_amber,
R.color.material_orange, R.color.material_deep_orange};
// SharedPreferences constants
@Preference(type = BOOLEAN, exportable = false)
String KEY_UCD_DATA_PROFILING = "ucd_data_profiling";
@Preference(type = BOOLEAN, exportable = false)
String KEY_SPICE_DATA_PROFILING = "spice_data_profiling";
@Preference(type = STRING, exportable = false)
String KEY_SPICE_DEVICE_ID = "spice_device_id";
}

View File

@ -1,47 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.activity;
import android.app.FragmentManager;
import android.os.Bundle;
import android.view.MenuItem;
import org.mariotaku.twidere.fragment.DataProfilingSettingsFragment;
public class DataProfilingSettingsActivity extends BasePreferenceActivity {
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case MENU_HOME: {
navigateUpFromSameTask();
return true;
}
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final FragmentManager fm = getFragmentManager();
fm.beginTransaction().replace(android.R.id.content, new DataProfilingSettingsFragment()).commit();
}
}

View File

@ -105,6 +105,7 @@ import org.mariotaku.twidere.service.BackgroundOperationService;
import org.mariotaku.twidere.task.TwidereAsyncTask;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ContentValuesCreator;
import android.support.v7.widget.FixedLinearLayoutManager;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.MathUtils;
import org.mariotaku.twidere.util.ParseUtils;
@ -643,7 +644,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
mAccountSelectorButton.setOnClickListener(this);
mLocationContainer.setOnClickListener(this);
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
final LinearLayoutManager linearLayoutManager = new FixedLinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
linearLayoutManager.setStackFromEnd(true);
mAccountSelector.setLayoutManager(linearLayoutManager);

View File

@ -213,34 +213,29 @@ public class CustomTabEditorActivity extends BaseSupportDialogActivity implement
final TextView text1 = (TextView) view.findViewById(android.R.id.text1);
final TextView text2 = (TextView) view.findViewById(android.R.id.text2);
final ImageView icon = (ImageView) view.findViewById(android.R.id.icon);
final boolean display_profile_image = mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true);
final boolean nickname_only = mPreferences.getBoolean(KEY_NICKNAME_ONLY, false);
final boolean display_name = mPreferences.getBoolean(KEY_NAME_FIRST, true);
final boolean displayProfileImage = mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true);
final boolean displayName = mPreferences.getBoolean(KEY_NAME_FIRST, true);
text1.setVisibility(View.VISIBLE);
text2.setVisibility(View.VISIBLE);
icon.setVisibility(display_profile_image ? View.VISIBLE : View.GONE);
icon.setVisibility(displayProfileImage ? View.VISIBLE : View.GONE);
if (value instanceof ParcelableUser) {
final ParcelableUser user = (ParcelableUser) value;
final String nick = getUserNickname(this, user.id);
text1.setText(TextUtils.isEmpty(nick) ? user.name : nickname_only ? nick : getString(
R.string.name_with_nickname, user.name, nick));
text1.setText(getUserNickname(this, user.id,user.name));
text2.setText("@" + user.screen_name);
if (display_profile_image) {
if (displayProfileImage) {
mImageLoader.displayProfileImage(icon, user.profile_image_url);
}
} else if (value instanceof ParcelableUserList) {
final ParcelableUserList user_list = (ParcelableUserList) value;
final String created_by;
if (display_name) {
if (displayName) {
created_by = "@" + user_list.user_screen_name;
} else {
final String nick = getUserNickname(this, user_list.user_id);
created_by = TextUtils.isEmpty(nick) ? user_list.user_name : nickname_only ? nick : getString(
R.string.name_with_nickname, user_list.user_name, nick);
created_by = getUserNickname(this, user_list.user_id,user_list.user_name);
}
text1.setText(user_list.name);
text2.setText(getString(R.string.created_by, created_by));
if (display_profile_image) {
if (displayProfileImage) {
mImageLoader.displayProfileImage(icon, user_list.user_profile_image_url);
}
} else if (value instanceof CharSequence) {

View File

@ -72,7 +72,6 @@ import com.squareup.otto.Subscribe;
import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.DataProfilingSettingsActivity;
import org.mariotaku.twidere.activity.SettingsActivity;
import org.mariotaku.twidere.activity.SettingsWizardActivity;
import org.mariotaku.twidere.activity.iface.IControlBarActivity;
@ -808,18 +807,19 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
private void showDataProfilingRequest() {
//spice
if (mPreferences.getBoolean(KEY_SHOW_UCD_DATA_PROFILING_REQUEST, true) || mPreferences.getBoolean(KEY_SHOW_SPICE_DATA_PROFILING_REQUEST, true)) {
final Intent intent = new Intent(this, DataProfilingSettingsActivity.class);
final PendingIntent content_intent = PendingIntent.getActivity(this, 0, intent, 0);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setAutoCancel(true);
builder.setSmallIcon(R.drawable.ic_stat_info);
builder.setTicker(getString(R.string.data_profiling_notification_ticker));
builder.setContentTitle(getString(R.string.data_profiling_notification_title));
builder.setContentText(getString(R.string.data_profiling_notification_desc));
builder.setContentIntent(content_intent);
mNotificationManager.notify(NOTIFICATION_ID_DATA_PROFILING, builder.build());
if (mPreferences.contains(KEY_UCD_DATA_PROFILING) && mPreferences.contains(KEY_SPICE_DATA_PROFILING)) {
return;
}
final Intent intent = new Intent(this, UsageStatisticsActivity.class);
final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setAutoCancel(true);
builder.setSmallIcon(R.drawable.ic_stat_info);
builder.setTicker(getString(R.string.usage_statistics));
builder.setContentTitle(getString(R.string.usage_statistics));
builder.setContentText(getString(R.string.usage_statistics_notification_summary));
builder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID_DATA_PROFILING, builder.build());
}
private void triggerActionsClick() {
@ -944,7 +944,7 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
protected int[] doInBackground(final Void... params) {
final int tabCount = mIndicator.getCount();
final int[] result = new int[tabCount];
for (int i = 0, j = tabCount; i < j; i++) {
for (int i = 0; i < tabCount; i++) {
result[i] = UnreadCountUtils.getUnreadCount(mContext, i);
}
return result;

View File

@ -441,9 +441,7 @@ public class QuickSearchBarActivity extends ThemedFragmentActivity implements On
final TextView text1 = (TextView) view.findViewById(android.R.id.text1);
final TextView text2 = (TextView) view.findViewById(android.R.id.text2);
final String nick = getUserNickname(context, user.id);
text1.setText(TextUtils.isEmpty(nick) ? user.name : adapter.isNicknameOnly() ? nick :
context.getString(R.string.name_with_nickname, user.name, nick));
text1.setText(getUserNickname(context, user.id, user.name));
text2.setVisibility(View.VISIBLE);
text2.setText("@" + user.screen_name);
icon.clearColorFilter();
@ -497,15 +495,12 @@ public class QuickSearchBarActivity extends ThemedFragmentActivity implements On
private final Context mContext;
private final LayoutInflater mInflater;
private final MediaLoaderWrapper mImageLoader;
private final boolean mNicknameOnly;
private List<SuggestionItem> mData;
SuggestionsAdapter(Context context) {
mContext = context;
mInflater = LayoutInflater.from(context);
mImageLoader = TwidereApplication.getInstance(context).getImageLoaderWrapper();
final SharedPreferences pref = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
mNicknameOnly = pref.getBoolean(KEY_NICKNAME_ONLY, false);
}
public Context getContext() {
@ -562,10 +557,6 @@ public class QuickSearchBarActivity extends ThemedFragmentActivity implements On
return 4;
}
public boolean isNicknameOnly() {
return mNicknameOnly;
}
public void removeItemAt(int position) {
if (mData == null) return;
mData.remove(position);

View File

@ -0,0 +1,46 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.activity.support;
import android.content.Intent;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.SettingsActivity;
import org.mariotaku.twidere.fragment.SettingsDetailsFragment;
public class UsageStatisticsActivity extends BaseActionBarActivity implements Constants {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Bundle fragmentArgs = new Bundle();
fragmentArgs.putInt(EXTRA_RESID, R.xml.preferences_usage_statistics);
final Intent intent = new Intent(this, SettingsActivity.class);
intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, SettingsDetailsFragment.class.getName());
intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT_ARGUMENTS, fragmentArgs);
intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT_TITLE, R.string.usage_statistics);
startActivity(intent);
finish();
}
}

View File

@ -39,8 +39,8 @@ import org.mariotaku.twidere.fragment.support.UserFragment;
import org.mariotaku.twidere.model.ParcelableActivity;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils;
@ -73,7 +73,6 @@ public abstract class AbsActivitiesAdapter<Data> extends Adapter<ViewHolder> imp
private final boolean mCompactCards;
private final boolean mDisplayMediaPreview;
private final boolean mNameFirst;
private final boolean mNicknameOnly;
private boolean mLoadMoreIndicatorEnabled;
private ActivityAdapterListener mActivityAdapterListener;
@ -93,7 +92,6 @@ public abstract class AbsActivitiesAdapter<Data> extends Adapter<ViewHolder> imp
mMediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
mDisplayMediaPreview = preferences.getBoolean(KEY_MEDIA_PREVIEW, false);
mNameFirst = preferences.getBoolean(KEY_NAME_FIRST, true);
mNicknameOnly = preferences.getBoolean(KEY_NICKNAME_ONLY, false);
}
public abstract ParcelableActivity getActivity(int position);
@ -147,10 +145,6 @@ public abstract class AbsActivitiesAdapter<Data> extends Adapter<ViewHolder> imp
return mNameFirst;
}
public boolean isNicknameOnly() {
return mNicknameOnly;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
@ -212,7 +206,7 @@ public abstract class AbsActivitiesAdapter<Data> extends Adapter<ViewHolder> imp
final StatusViewHolder statusViewHolder = (StatusViewHolder) holder;
statusViewHolder.displayStatus(getContext(), getImageLoader(), getImageLoadingHandler(),
getTwitterWrapper(), isMediaPreviewDisplayed(), false, false, isNameFirst(),
isNicknameOnly(), getProfileImageStyle(), getMediaPreviewStyle(), status, null, true);
getProfileImageStyle(), getMediaPreviewStyle(), status, null, true);
break;
}
case ITEM_VIEW_TYPE_TITLE_SUMMARY: {

View File

@ -18,8 +18,8 @@ import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.fragment.support.UserFragment;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils;
@ -47,7 +47,6 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
private final int mProfileImageStyle, mMediaPreviewStyle;
private final boolean mCompactCards;
private final boolean mNameFirst;
private final boolean mNicknameOnly;
private final boolean mDisplayMediaPreview;
private boolean mLoadMoreIndicatorEnabled;
private StatusAdapterListener mStatusAdapterListener;
@ -69,7 +68,6 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
mProfileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
mMediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
mNameFirst = preferences.getBoolean(KEY_NAME_FIRST, true);
mNicknameOnly = preferences.getBoolean(KEY_NICKNAME_ONLY, false);
mDisplayMediaPreview = preferences.getBoolean(KEY_MEDIA_PREVIEW, false);
setShowInReplyTo(true);
}
@ -133,11 +131,6 @@ public abstract class AbsStatusesAdapter<D> extends Adapter<ViewHolder> implemen
return mNameFirst;
}
@Override
public boolean isNicknameOnly() {
return mNicknameOnly;
}
public boolean isShowInReplyTo() {
return mShowInReplyTo;
}

View File

@ -114,10 +114,6 @@ public class AccountsAdapter extends SimpleDragSortCursorAdapter implements Cons
return mDisplayProfileImage;
}
@Override
public boolean isNicknameOnly() {
return false;
}
@Override
public boolean isShowAccountColor() {
@ -146,11 +142,6 @@ public class AccountsAdapter extends SimpleDragSortCursorAdapter implements Cons
}
@Override
public void setNicknameOnly(boolean nicknameOnly) {
}
@Override
public void setShowAccountColor(boolean show) {

View File

@ -40,7 +40,7 @@ public class BaseArrayAdapter<T> extends ArrayAdapter<T> implements IBaseAdapter
private float mTextSize;
private int mLinkHighlightOption;
private boolean mDisplayProfileImage, mNicknameOnly, mDisplayNameFirst, mShowAccountColor;
private boolean mDisplayProfileImage, mDisplayNameFirst, mShowAccountColor;
private final SharedPreferences mNicknamePrefs, mColorPrefs;
private final MediaLoaderWrapper mImageLoader;
@ -89,11 +89,6 @@ public class BaseArrayAdapter<T> extends ArrayAdapter<T> implements IBaseAdapter
return mDisplayProfileImage;
}
@Override
public final boolean isNicknameOnly() {
return mNicknameOnly;
}
@Override
public final boolean isShowAccountColor() {
return mShowAccountColor;
@ -101,8 +96,8 @@ public class BaseArrayAdapter<T> extends ArrayAdapter<T> implements IBaseAdapter
@Override
public void onSharedPreferenceChanged(final SharedPreferences preferences, final String key) {
if (KEY_NICKNAME_ONLY.equals(key) || KEY_DISPLAY_PROFILE_IMAGE.equals(key)
|| KEY_MEDIA_PREVIEW_STYLE.equals(key) || KEY_DISPLAY_SENSITIVE_CONTENTS.equals(key)) {
if (KEY_DISPLAY_PROFILE_IMAGE.equals(key) || KEY_MEDIA_PREVIEW_STYLE.equals(key)
|| KEY_DISPLAY_SENSITIVE_CONTENTS.equals(key)) {
notifyDataSetChanged();
}
}
@ -125,11 +120,6 @@ public class BaseArrayAdapter<T> extends ArrayAdapter<T> implements IBaseAdapter
mLinkHighlightOption = optionInt;
}
@Override
public final void setNicknameOnly(final boolean nicknameOnly) {
mNicknameOnly = nicknameOnly;
}
@Override
public final void setShowAccountColor(final boolean show) {
mShowAccountColor = show;

View File

@ -19,8 +19,6 @@
package org.mariotaku.twidere.adapter;
import static org.mariotaku.twidere.util.Utils.getLinkHighlightOptionInt;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
@ -33,122 +31,112 @@ import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.OnLinkClickHandler;
import org.mariotaku.twidere.util.TwidereLinkify;
import static org.mariotaku.twidere.util.Utils.getLinkHighlightOptionInt;
public class BaseCursorAdapter extends SimpleCursorAdapter implements IBaseAdapter, OnSharedPreferenceChangeListener {
private final TwidereLinkify mLinkify;
private final TwidereLinkify mLinkify;
private float mTextSize;
private float mTextSize;
private int mLinkHighlightOption, mLinkHighlightColor;
private int mLinkHighlightOption, mLinkHighlightColor;
private boolean mDisplayProfileImage, mNicknameOnly, mDisplayNameFirst, mShowAccountColor;
private boolean mDisplayProfileImage, mDisplayNameFirst, mShowAccountColor;
private final SharedPreferences mNicknamePrefs, mColorPrefs;
private final MediaLoaderWrapper mImageLoader;
private final SharedPreferences mNicknamePrefs, mColorPrefs;
private final MediaLoaderWrapper mImageLoader;
public BaseCursorAdapter(final Context context, final int layout, final Cursor c, final String[] from,
final int[] to) {
this(context, layout, c, from, to, 0);
}
public BaseCursorAdapter(final Context context, final int layout, final Cursor c, final String[] from,
final int[] to) {
this(context, layout, c, from, to, 0);
}
public BaseCursorAdapter(final Context context, final int layout, final Cursor c, final String[] from,
final int[] to, final int flags) {
super(context, layout, c, from, to, flags);
final TwidereApplication app = TwidereApplication.getInstance(context);
mLinkify = new TwidereLinkify(new OnLinkClickHandler(context, app.getMultiSelectManager()));
mImageLoader = app.getImageLoaderWrapper();
mNicknamePrefs = context.getSharedPreferences(USER_NICKNAME_PREFERENCES_NAME, Context.MODE_PRIVATE);
mColorPrefs = context.getSharedPreferences(USER_COLOR_PREFERENCES_NAME, Context.MODE_PRIVATE);
mNicknamePrefs.registerOnSharedPreferenceChangeListener(this);
mColorPrefs.registerOnSharedPreferenceChangeListener(this);
}
@Override
public MediaLoaderWrapper getImageLoader() {
return mImageLoader;
}
public BaseCursorAdapter(final Context context, final int layout, final Cursor c, final String[] from,
final int[] to, final int flags) {
super(context, layout, c, from, to, flags);
final TwidereApplication app = TwidereApplication.getInstance(context);
mLinkify = new TwidereLinkify(new OnLinkClickHandler(context, app.getMultiSelectManager()));
mImageLoader = app.getImageLoaderWrapper();
mNicknamePrefs = context.getSharedPreferences(USER_NICKNAME_PREFERENCES_NAME, Context.MODE_PRIVATE);
mColorPrefs = context.getSharedPreferences(USER_COLOR_PREFERENCES_NAME, Context.MODE_PRIVATE);
mNicknamePrefs.registerOnSharedPreferenceChangeListener(this);
mColorPrefs.registerOnSharedPreferenceChangeListener(this);
}
@Override
public final int getLinkHighlightOption() {
return mLinkHighlightOption;
}
public final TwidereLinkify getLinkify() {
return mLinkify;
}
@Override
public final float getTextSize() {
return mTextSize;
}
@Override
public final boolean isDisplayNameFirst() {
return mDisplayNameFirst;
}
@Override
public final boolean isDisplayProfileImage() {
return mDisplayProfileImage;
}
@Override
public final boolean isNicknameOnly() {
return mNicknameOnly;
}
@Override
public final boolean isShowAccountColor() {
return mShowAccountColor;
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
notifyDataSetChanged();
}
@Override
public final void setDisplayNameFirst(final boolean name_first) {
if (mDisplayNameFirst == name_first) return;
mDisplayNameFirst = name_first;
notifyDataSetChanged();
}
@Override
public final void setDisplayProfileImage(final boolean display) {
if (display == mDisplayProfileImage) return;
mDisplayProfileImage = display;
notifyDataSetChanged();
}
public MediaLoaderWrapper getImageLoader() {
return mImageLoader;
}
@Override
public final void setLinkHighlightOption(final String option) {
final int option_int = getLinkHighlightOptionInt(option);
if (option_int == mLinkHighlightOption) return;
mLinkHighlightOption = option_int;
mLinkify.setHighlightOption(option_int);
notifyDataSetChanged();
}
public final int getLinkHighlightOption() {
return mLinkHighlightOption;
}
@Override
public final void setNicknameOnly(final boolean nicknameOnly) {
if (mNicknameOnly == nicknameOnly) return;
mNicknameOnly = nicknameOnly;
notifyDataSetChanged();
}
public final TwidereLinkify getLinkify() {
return mLinkify;
}
@Override
public final void setShowAccountColor(final boolean show) {
if (show == mShowAccountColor) return;
mShowAccountColor = show;
notifyDataSetChanged();
}
@Override
public final float getTextSize() {
return mTextSize;
}
@Override
public final void setTextSize(final float textSize) {
if (textSize == mTextSize) return;
mTextSize = textSize;
notifyDataSetChanged();
}
@Override
public final boolean isDisplayNameFirst() {
return mDisplayNameFirst;
}
@Override
public final boolean isDisplayProfileImage() {
return mDisplayProfileImage;
}
@Override
public final boolean isShowAccountColor() {
return mShowAccountColor;
}
@Override
public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
notifyDataSetChanged();
}
@Override
public final void setDisplayNameFirst(final boolean name_first) {
if (mDisplayNameFirst == name_first) return;
mDisplayNameFirst = name_first;
notifyDataSetChanged();
}
@Override
public final void setDisplayProfileImage(final boolean display) {
if (display == mDisplayProfileImage) return;
mDisplayProfileImage = display;
notifyDataSetChanged();
}
@Override
public final void setLinkHighlightOption(final String option) {
final int option_int = getLinkHighlightOptionInt(option);
if (option_int == mLinkHighlightOption) return;
mLinkHighlightOption = option_int;
mLinkify.setHighlightOption(option_int);
notifyDataSetChanged();
}
@Override
public final void setShowAccountColor(final boolean show) {
if (show == mShowAccountColor) return;
mShowAccountColor = show;
notifyDataSetChanged();
}
@Override
public final void setTextSize(final float textSize) {
if (textSize == mTextSize) return;
mTextSize = textSize;
notifyDataSetChanged();
}
}

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere.adapter;
import android.content.Context;
import android.database.Cursor;
import android.support.v7.widget.RecyclerView;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatus.CursorIndices;
@ -48,18 +49,12 @@ public class CursorStatusesAdapter extends AbsStatusesAdapter<Cursor> {
@Override
public long getItemId(int position) {
if (position == getStatusesCount()) return -1;
if (position == getStatusesCount()) return Long.MAX_VALUE;
final Cursor c = mCursor;
if (c != null && !c.isClosed() && c.moveToPosition(position)) {
final long account_id = c.getLong(mIndices.account_id);
final long id = c.getLong(mIndices.status_id);
final int prime = 31;
int result = 1;
result = prime * result + (int) (account_id ^ account_id >>> 32);
result = prime * result + (int) (id ^ id >>> 32);
return result;
return c.getLong(mIndices._id);
}
return -1;
return RecyclerView.NO_ID;
}
@Override
@ -86,12 +81,12 @@ public class CursorStatusesAdapter extends AbsStatusesAdapter<Cursor> {
@Override
public long getStatusId(int position) {
if (position == getStatusesCount()) return position;
if (position == getStatusesCount()) return -1;
final Cursor c = mCursor;
if (c != null && !c.isClosed() && c.moveToPosition(position)) {
return c.getLong(mIndices.status_id);
}
return position;
return -1;
}
@Override

View File

@ -34,8 +34,8 @@ import org.mariotaku.twidere.adapter.iface.IContentCardAdapter;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.ConversationEntries;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.MultiSelectManager;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.Utils;
@ -44,18 +44,43 @@ import org.mariotaku.twidere.view.holder.MessageEntryViewHolder;
public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Constants, IContentCardAdapter, OnClickListener {
public static final int ITEM_VIEW_TYPE_MESSAGE = 0;
public static final int ITEM_VIEW_TYPE_LOAD_INDICATOR = 1;
private final Context mContext;
private final LayoutInflater mInflater;
private final MediaLoaderWrapper mImageLoader;
private final MultiSelectManager mMultiSelectManager;
private final boolean mNicknameOnly;
private boolean mLoadMoreIndicatorEnabled;
private final int mTextSize;
private final int mProfileImageStyle;
private final int mMediaPreviewStyle;
private boolean mLoadMoreIndicatorEnabled;
private Cursor mCursor;
private MessageEntriesAdapterListener mListener;
public MessageEntriesAdapter(final Context context) {
mContext = context;
mInflater = LayoutInflater.from(context);
final TwidereApplication app = TwidereApplication.getInstance(context);
mMultiSelectManager = app.getMultiSelectManager();
mImageLoader = app.getImageLoaderWrapper();
final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(context,
SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
mProfileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
mMediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
mTextSize = preferences.getInt(KEY_TEXT_SIZE, context.getResources().getInteger(R.integer.default_text_size));
}
public DirectMessageEntry getEntry(final int position) {
final Cursor c = mCursor;
if (c == null || c.isClosed() || !c.moveToPosition(position)) return null;
return new DirectMessageEntry(c);
}
public MediaLoaderWrapper getImageLoader() {
return mImageLoader;
}
public Context getContext() {
return mContext;
}
@ -85,21 +110,16 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
return mTextSize;
}
@Override
public void setLoadMoreIndicatorEnabled(boolean enabled) {
if (mLoadMoreIndicatorEnabled == enabled) return;
mLoadMoreIndicatorEnabled = enabled;
notifyDataSetChanged();
}
@Override
public boolean hasLoadMoreIndicator() {
return mLoadMoreIndicatorEnabled;
}
public MediaLoaderWrapper getImageLoader() {
return mImageLoader;
@Override
public void setLoadMoreIndicatorEnabled(boolean enabled) {
if (mLoadMoreIndicatorEnabled == enabled) return;
mLoadMoreIndicatorEnabled = enabled;
notifyDataSetChanged();
}
@Override
@ -112,25 +132,23 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
}
public boolean isNicknameOnly() {
return mNicknameOnly;
}
public static final int ITEM_VIEW_TYPE_MESSAGE = 0;
public static final int ITEM_VIEW_TYPE_LOAD_INDICATOR = 1;
@Override
public int getItemViewType(int position) {
if (position == getMessagesCount()) {
return ITEM_VIEW_TYPE_LOAD_INDICATOR;
}
return ITEM_VIEW_TYPE_MESSAGE;
}
private int getMessagesCount() {
final Cursor c = mCursor;
if (c == null || c.isClosed()) return 0;
return c.getCount();
public void onClick(final View view) {
// if (mMultiSelectManager.isActive()) return;
// final Object tag = view.getTag();
// final int position = tag instanceof Integer ? (Integer) tag : -1;
// if (position == -1) return;
// switch (view.getId()) {
// case R.id.profile_image: {
// if (mContext instanceof Activity) {
// final long account_id = getAccountId(position);
// final long user_id = getConversationId(position);
// final String screen_name = getScreenName(position);
// openUserProfile(mContext, account_id, user_id, screen_name, null);
// }
// break;
// }
// }
}
@Override
@ -160,6 +178,19 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
}
}
@Override
public int getItemViewType(int position) {
if (position == getMessagesCount()) {
return ITEM_VIEW_TYPE_LOAD_INDICATOR;
}
return ITEM_VIEW_TYPE_MESSAGE;
}
@Override
public final int getItemCount() {
return getMessagesCount() + (mLoadMoreIndicatorEnabled ? 1 : 0);
}
@Override
public void onItemActionClick(ViewHolder holder, int id, int position) {
@ -180,23 +211,18 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
notifyDataSetChanged();
}
@Override
public final int getItemCount() {
return getMessagesCount() + (mLoadMoreIndicatorEnabled ? 1 : 0);
public void setListener(MessageEntriesAdapterListener listener) {
mListener = listener;
}
public MessageEntriesAdapter(final Context context) {
mContext = context;
mInflater = LayoutInflater.from(context);
final TwidereApplication app = TwidereApplication.getInstance(context);
mMultiSelectManager = app.getMultiSelectManager();
mImageLoader = app.getImageLoaderWrapper();
final SharedPreferencesWrapper preferences = SharedPreferencesWrapper.getInstance(context,
SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
mProfileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
mMediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
mTextSize = preferences.getInt(KEY_TEXT_SIZE, context.getResources().getInteger(R.integer.default_text_size));
mNicknameOnly = preferences.getBoolean(KEY_NICKNAME_ONLY, false);
private int getMessagesCount() {
final Cursor c = mCursor;
if (c == null || c.isClosed()) return 0;
return c.getCount();
}
public interface MessageEntriesAdapterListener {
public void onEntryClick(int position, DirectMessageEntry entry);
}
public static class DirectMessageEntry {
@ -213,37 +239,4 @@ public class MessageEntriesAdapter extends Adapter<ViewHolder> implements Consta
}
public DirectMessageEntry getEntry(final int position) {
final Cursor c = mCursor;
if (c == null || c.isClosed() || !c.moveToPosition(position)) return null;
return new DirectMessageEntry(c);
}
@Override
public void onClick(final View view) {
// if (mMultiSelectManager.isActive()) return;
// final Object tag = view.getTag();
// final int position = tag instanceof Integer ? (Integer) tag : -1;
// if (position == -1) return;
// switch (view.getId()) {
// case R.id.profile_image: {
// if (mContext instanceof Activity) {
// final long account_id = getAccountId(position);
// final long user_id = getConversationId(position);
// final String screen_name = getScreenName(position);
// openUserProfile(mContext, account_id, user_id, screen_name, null);
// }
// break;
// }
// }
}
public void setListener(MessageEntriesAdapterListener listener) {
mListener = listener;
}
public interface MessageEntriesAdapterListener {
public void onEntryClick(int position, DirectMessageEntry entry);
}
}

View File

@ -90,25 +90,25 @@ public class ParcelableUserListsListAdapter extends BaseArrayAdapter<ParcelableU
holder.position = position;
final ParcelableUserList user_list = getItem(position);
final String display_name = UserColorNameUtils.getDisplayName(mContext, user_list.user_id, user_list.user_name,
user_list.user_screen_name, isDisplayNameFirst(), isNicknameOnly(), false);
final ParcelableUserList userList = getItem(position);
final String displayName = UserColorNameUtils.getDisplayName(mContext, userList.user_id, userList.user_name,
userList.user_screen_name, isDisplayNameFirst(), false);
holder.setTextSize(getTextSize());
holder.name.setText(user_list.name);
holder.created_by.setText(mContext.getString(R.string.created_by, display_name));
holder.name.setText(userList.name);
holder.created_by.setText(mContext.getString(R.string.created_by, displayName));
if (holder.description != null) {
holder.description.setVisibility(TextUtils.isEmpty(user_list.description) ? View.GONE : View.VISIBLE);
holder.description.setText(user_list.description);
holder.description.setVisibility(TextUtils.isEmpty(userList.description) ? View.GONE : View.VISIBLE);
holder.description.setText(userList.description);
}
if (holder.members_count != null) {
holder.members_count.setText(getLocalizedNumber(mLocale, user_list.members_count));
holder.members_count.setText(getLocalizedNumber(mLocale, userList.members_count));
}
if (holder.subscribers_count != null) {
holder.subscribers_count.setText(getLocalizedNumber(mLocale, user_list.subscribers_count));
holder.subscribers_count.setText(getLocalizedNumber(mLocale, userList.subscribers_count));
}
holder.profile_image.setVisibility(isDisplayProfileImage() ? View.VISIBLE : View.GONE);
if (isDisplayProfileImage()) {
mImageLoader.displayProfileImage(holder.profile_image, user_list.user_profile_image_url);
mImageLoader.displayProfileImage(holder.profile_image, userList.user_profile_image_url);
} else {
mImageLoader.cancelDisplayTask(holder.profile_image);
}

View File

@ -104,9 +104,7 @@ public class ParcelableUsersAdapter extends BaseArrayAdapter<ParcelableUser> imp
} else {
holder.profile_type.setImageDrawable(null);
}
final String nick = getUserNickname(mContext, user.id);
holder.name.setText(TextUtils.isEmpty(nick) ? user.name : isNicknameOnly() ? nick : mContext.getString(
R.string.name_with_nickname, user.name, nick));
holder.name.setText(getUserNickname(mContext, user.id, user.name));
holder.screen_name.setText("@" + user.screen_name);
holder.description.setVisibility(TextUtils.isEmpty(user.description_unescaped) ? View.GONE : View.VISIBLE);
holder.description.setText(user.description_unescaped);

View File

@ -34,7 +34,6 @@ import org.mariotaku.twidere.view.holder.TwoLineWithIconViewHolder;
import java.util.List;
import static org.mariotaku.twidere.util.Utils.configBaseAdapter;
import static org.mariotaku.twidere.util.UserColorNameUtils.getDisplayName;
public class SimpleParcelableUserListsAdapter extends BaseArrayAdapter<ParcelableUserList> implements IBaseAdapter {
@ -75,7 +74,7 @@ public class SimpleParcelableUserListsAdapter extends BaseArrayAdapter<Parcelabl
final ParcelableUserList user_list = getItem(position);
final String display_name = UserColorNameUtils.getDisplayName(mContext, user_list.user_id, user_list.user_name,
user_list.user_screen_name, isDisplayNameFirst(), isNicknameOnly(), false);
user_list.user_screen_name, isDisplayNameFirst(), false);
holder.text1.setText(user_list.name);
holder.text2.setText(mContext.getString(R.string.created_by, display_name));
holder.icon.setVisibility(isDisplayProfileImage() ? View.VISIBLE : View.GONE);

View File

@ -20,7 +20,6 @@
package org.mariotaku.twidere.adapter;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
@ -75,9 +74,7 @@ public class SimpleParcelableUsersAdapter extends BaseArrayAdapter<ParcelableUse
holder.text1.setCompoundDrawablesWithIntrinsicBounds(0, 0,
getUserTypeIconRes(user.is_verified, user.is_protected), 0);
final String nick = getUserNickname(mContext, user.id);
holder.text1.setText(TextUtils.isEmpty(nick) ? user.name : isNicknameOnly() ? nick : mContext.getString(
R.string.name_with_nickname, user.name, nick));
holder.text1.setText(getUserNickname(mContext, user.id, user.name));
holder.text2.setText("@" + user.screen_name);
holder.icon.setVisibility(isDisplayProfileImage() ? View.VISIBLE : View.GONE);
if (isDisplayProfileImage()) {

View File

@ -24,8 +24,8 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.v4.widget.SimpleCursorAdapter;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.FilterQueryProvider;
@ -44,6 +44,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedValues;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.ParseUtils;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.Utils;
import static org.mariotaku.twidere.util.UserColorNameUtils.getUserNickname;
@ -53,14 +54,20 @@ public class UserHashtagAutoCompleteAdapter extends SimpleCursorAdapter implemen
private static final String[] FROM = new String[0];
private static final int[] TO = new int[0];
@NonNull
private final ContentResolver mResolver;
@NonNull
private final SQLiteDatabase mDatabase;
@NonNull
private final MediaLoaderWrapper mProfileImageLoader;
private final SharedPreferences mPreferences, mUserNicknamePreferences;
@NonNull
private final SharedPreferencesWrapper mPreferences;
@NonNull
private final SharedPreferences mUserNicknamePreferences;
private final EditText mEditText;
private final boolean mDisplayProfileImage, mNicknameOnly;
private final boolean mDisplayProfileImage;
private int mProfileImageUrlIdx, mNameIdx, mScreenNameIdx, mUserIdIdx;
private char mToken = '@';
@ -72,14 +79,13 @@ public class UserHashtagAutoCompleteAdapter extends SimpleCursorAdapter implemen
public UserHashtagAutoCompleteAdapter(final Context context, final EditText view) {
super(context, R.layout.list_item_two_line_small, null, FROM, TO, 0);
mEditText = view;
mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
mPreferences = SharedPreferencesWrapper.getInstance(context, SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
mUserNicknamePreferences = context.getSharedPreferences(USER_NICKNAME_PREFERENCES_NAME, Context.MODE_PRIVATE);
mResolver = context.getContentResolver();
final TwidereApplication app = TwidereApplication.getInstance(context);
mProfileImageLoader = app != null ? app.getImageLoaderWrapper() : null;
mDatabase = app != null ? app.getSQLiteDatabase() : null;
mDisplayProfileImage = mPreferences != null && mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true);
mNicknameOnly = mPreferences != null && mPreferences.getBoolean(KEY_NICKNAME_ONLY, false);
mProfileImageLoader = app.getImageLoaderWrapper();
mDatabase = app.getSQLiteDatabase();
mDisplayProfileImage = mPreferences.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true);
}
public UserHashtagAutoCompleteAdapter(final EditText view) {
@ -97,13 +103,7 @@ public class UserHashtagAutoCompleteAdapter extends SimpleCursorAdapter implemen
icon.setImageDrawable(null);
if (mScreenNameIdx != -1 && mNameIdx != -1 && mUserIdIdx != -1) {
final String nick = getUserNickname(context, cursor.getLong(mUserIdIdx));
final String name = cursor.getString(mNameIdx);
if (TextUtils.isEmpty(nick)) {
text1.setText(name);
} else {
text1.setText(mNicknameOnly ? nick : context.getString(R.string.name_with_nickname, name, nick));
}
text1.setText(getUserNickname(context, cursor.getLong(mUserIdIdx), cursor.getString(mNameIdx)));
text2.setText("@" + cursor.getString(mScreenNameIdx));
} else {
text1.setText("#" + cursor.getString(mNameIdx));
@ -111,10 +111,11 @@ public class UserHashtagAutoCompleteAdapter extends SimpleCursorAdapter implemen
}
icon.setVisibility(mDisplayProfileImage ? View.VISIBLE : View.GONE);
if (mProfileImageUrlIdx != -1) {
if (mDisplayProfileImage && mProfileImageLoader != null) {
final String profile_image_url_string = cursor.getString(mProfileImageUrlIdx);
mProfileImageLoader.displayProfileImage(icon, profile_image_url_string);
if (mDisplayProfileImage) {
final String profileImageUrl = cursor.getString(mProfileImageUrlIdx);
mProfileImageLoader.displayProfileImage(icon, profileImageUrl);
} else {
mProfileImageLoader.cancelDisplayTask(icon);
// icon.setImageResource(R.drawable.ic_profile_image_default);
}
} else {

View File

@ -36,8 +36,6 @@ public interface IBaseAdapter extends Constants, ListAdapter {
public boolean isDisplayProfileImage();
public boolean isNicknameOnly();
public boolean isShowAccountColor();
public void notifyDataSetChanged();
@ -48,8 +46,6 @@ public interface IBaseAdapter extends Constants, ListAdapter {
public void setLinkHighlightOption(String option);
public void setNicknameOnly(boolean nicknameOnly);
public void setShowAccountColor(boolean show);
public void setTextSize(float textSize);

View File

@ -18,8 +18,6 @@ public interface IStatusesAdapter<Data> extends IContentCardAdapter, StatusClick
boolean isNameFirst();
boolean isNicknameOnly();
void setData(Data data);
boolean shouldShowAccountsColor();

View File

@ -29,6 +29,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.AsyncTask;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.multidex.MultiDexApplication;
import com.nostra13.universalimageloader.cache.disc.DiskCache;
@ -150,10 +151,9 @@ public class TwidereApplication extends MultiDexApplication implements Constants
return mMediaLoaderWrapper = new MediaLoaderWrapper(getImageLoader(), getVideoLoader());
}
public static TwidereApplication getInstance(final Context context) {
if (context == null) return null;
final Context app = context.getApplicationContext();
return app instanceof TwidereApplication ? (TwidereApplication) app : null;
@NonNull
public static TwidereApplication getInstance(@NonNull final Context context) {
return (TwidereApplication) context.getApplicationContext();
}
public Bus getMessageBus() {

View File

@ -29,6 +29,7 @@ import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
@ -52,8 +53,6 @@ import org.mariotaku.twidere.fragment.support.BaseSupportListFragment;
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
import org.mariotaku.twidere.util.UserColorNameUtils;
import static org.mariotaku.twidere.util.UserColorNameUtils.getDisplayName;
public abstract class BaseFiltersFragment extends BaseSupportListFragment implements LoaderManager.LoaderCallbacks<Cursor>,
MultiChoiceModeListener {
@ -265,25 +264,23 @@ public abstract class BaseFiltersFragment extends BaseSupportListFragment implem
private int mUserIdIdx, mNameIdx, mScreenNameIdx;
private final boolean mNameFirst, mNicknameOnly;
private final boolean mNameFirst;
public FilterUsersListAdapter(final Context context) {
super(context, android.R.layout.simple_list_item_activated_1, null, new String[0], new int[0], 0);
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
Context.MODE_PRIVATE);
mNameFirst = prefs.getBoolean(KEY_NAME_FIRST, true);
mNicknameOnly = prefs.getBoolean(KEY_NICKNAME_ONLY, false);
}
@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
public void bindView(@NonNull final View view, final Context context, @NonNull final Cursor cursor) {
super.bindView(view, context, cursor);
final TextView text1 = (TextView) view.findViewById(android.R.id.text1);
final long user_id = cursor.getLong(mUserIdIdx);
final String name = cursor.getString(mNameIdx);
final String screen_name = cursor.getString(mScreenNameIdx);
final String display_name = UserColorNameUtils.getDisplayName(context, user_id, name, screen_name, mNameFirst,
mNicknameOnly);
final String display_name = UserColorNameUtils.getDisplayName(context, user_id, name, screen_name, mNameFirst);
text1.setText(display_name);
}

View File

@ -1,122 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.fragment;
import static org.mariotaku.twidere.util.Utils.closeSilently;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import edu.ucdavis.earlybird.CSVFileFilter;
import org.mariotaku.twidere.R;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
public class DataProfilingSettingsFragment extends BaseFragment implements OnClickListener {
private SharedPreferences mPreferences;
private Button mSaveButton, mPreviewButton;
private CheckBox mCheckBox;
private TextView mTextView;
private boolean mShowingPreview;
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
if (mPreferences.contains(KEY_UCD_DATA_PROFILING)) {
mCheckBox.setChecked(mPreferences.getBoolean(KEY_UCD_DATA_PROFILING, false));
//spice
mCheckBox.setChecked(mPreferences.getBoolean(KEY_SPICE_DATA_PROFILING, false));
//end
}
mSaveButton.setOnClickListener(this);
mPreviewButton.setOnClickListener(this);
}
@Override
public void onClick(final View v) {
switch (v.getId()) {
case R.id.save: {
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putBoolean(KEY_UCD_DATA_PROFILING, mCheckBox.isChecked());
editor.putBoolean(KEY_SHOW_UCD_DATA_PROFILING_REQUEST, false);
//spice
editor.putBoolean(KEY_SPICE_DATA_PROFILING, mCheckBox.isChecked());
editor.putBoolean(KEY_SHOW_SPICE_DATA_PROFILING_REQUEST, false);
//end
editor.apply();
getActivity().onBackPressed();
break;
}
case R.id.preview: {
if (!mShowingPreview) {
mTextView.setText(null);
final File dir = getActivity().getFilesDir();
for (final File file : dir.listFiles(new CSVFileFilter())) {
mTextView.append(file.getName() + ":\n------\n");
try {
final BufferedReader br = new BufferedReader(new FileReader(file));
String line = null;
int i = 0;
while ((line = br.readLine()) != null && i < 10) {
mTextView.append(line + "\n");
i++;
}
mTextView.append("------------\n\n");
closeSilently(br);
} catch (final IOException e) {
mTextView.append("Cannot read this file");
}
}
} else {
mTextView.setText(R.string.data_profiling_summary);
}
mShowingPreview = !mShowingPreview;
break;
}
}
}
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_data_profiling_settings, container, false);
mTextView = (TextView) view.findViewById(android.R.id.text1);
mCheckBox = (CheckBox) view.findViewById(R.id.checkbox);
mSaveButton = (Button) view.findViewById(R.id.save);
mPreviewButton = (Button) view.findViewById(R.id.preview);
return view;
}
}

View File

@ -45,6 +45,7 @@ import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
import org.mariotaku.twidere.model.ParcelableActivity;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import android.support.v7.widget.FixedLinearLayoutManager;
import org.mariotaku.twidere.util.SimpleDrawerCallback;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils;
@ -172,7 +173,7 @@ public abstract class AbsActivitiesFragment<Data> extends BaseSupportFragment im
mAdapter = onCreateAdapter(context, compact);
mAdapter.setLoadMoreIndicatorEnabled(true);
mAdapter.setListener(this);
final LinearLayoutManager layoutManager = new LinearLayoutManager(context);
final LinearLayoutManager layoutManager = new FixedLinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
if (compact) {

View File

@ -12,9 +12,11 @@ import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.Loader;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.support.v7.widget.FixedLinearLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.OnScrollListener;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@ -38,7 +40,8 @@ import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ColorUtils;
import org.mariotaku.twidere.util.ContentListScrollListener;
import org.mariotaku.twidere.util.ContentListScrollListener.ContentListAware;
import org.mariotaku.twidere.util.ContentListScrollListener.ContentListSupport;
import org.mariotaku.twidere.util.PositionManager;
import org.mariotaku.twidere.util.SimpleDrawerCallback;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils;
@ -56,7 +59,7 @@ import static org.mariotaku.twidere.util.Utils.setMenuForStatus;
*/
public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment implements LoaderCallbacks<Data>,
OnRefreshListener, DrawerCallback, RefreshScrollTopInterface, StatusAdapterListener,
ControlBarOffsetListener, ContentListAware {
ControlBarOffsetListener, ContentListSupport {
private final Object mStatusesBusCallback;
private AbsStatusesAdapter<Data> mAdapter;
@ -69,6 +72,7 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
private Rect mSystemWindowsInsets = new Rect();
private int mControlBarOffsetPixels;
private PopupMenu mPopupMenu;
private PositionManager mPositionManager;
protected AbsStatusesFragment() {
mStatusesBusCallback = createMessageBusCallback();
@ -109,10 +113,6 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
mDrawerCallback.topChanged(offset);
}
public AbsStatusesAdapter<Data> getAdapter() {
return mAdapter;
}
public SharedPreferences getSharedPreferences() {
if (mPreferences != null) return mPreferences;
return mPreferences = getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
@ -124,10 +124,20 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
return mSwipeRefreshLayout.isRefreshing();
}
public AbsStatusesAdapter<Data> getAdapter() {
return mAdapter;
}
public void setControlVisible(boolean visible) {
final FragmentActivity activity = getActivity();
if (activity instanceof BaseActionBarActivity) {
((BaseActionBarActivity) activity).setControlBarVisibleAnimate(visible);
}
}
public void setRefreshing(boolean refreshing) {
if (refreshing == mSwipeRefreshLayout.isRefreshing()) return;
if (!refreshing)
updateRefreshProgressOffset();
if (!refreshing) updateRefreshProgressOffset();
mSwipeRefreshLayout.setRefreshing(refreshing);
}
@ -147,6 +157,7 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mPositionManager = new PositionManager(getActivity());
final View view = getView();
if (view == null) throw new AssertionError();
final Context context = view.getContext();
@ -159,9 +170,10 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
R.color.bg_refresh_progress_color_light, R.color.bg_refresh_progress_color_dark);
mSwipeRefreshLayout.setProgressBackgroundColorSchemeResource(colorRes);
mAdapter = onCreateAdapter(context, compact);
mLayoutManager = new LinearLayoutManager(context);
mLayoutManager = new FixedLinearLayoutManager(context);
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setHasFixedSize(true);
if (compact) {
mRecyclerView.addItemDecoration(new DividerItemDecoration(context, mLayoutManager.getOrientation()));
}
@ -169,6 +181,14 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
final ContentListScrollListener scrollListener = new ContentListScrollListener(this);
scrollListener.setTouchSlop(ViewConfiguration.get(context).getScaledTouchSlop());
scrollListener.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
saveReadPosition();
}
}
});
mRecyclerView.setOnScrollListener(scrollListener);
mAdapter.setListener(this);
final Bundle loaderArgs = new Bundle(getArguments());
@ -391,15 +411,22 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
mAdapter.setData(data);
}
protected String getReadPositionTag() {
return null;
}
protected abstract boolean hasMoreData(Data data);
protected abstract AbsStatusesAdapter<Data> onCreateAdapter(Context context, boolean compact);
public void setControlVisible(boolean visible) {
final FragmentActivity activity = getActivity();
if (activity instanceof BaseActionBarActivity) {
((BaseActionBarActivity) activity).setControlBarVisibleAnimate(visible);
}
protected void saveReadPosition() {
final String readPositionTag = getReadPositionTag();
if (readPositionTag == null) return;
final int position = mLayoutManager.findFirstVisibleItemPosition();
if (position == RecyclerView.NO_POSITION) return;
final ParcelableStatus status = mAdapter.getStatus(position);
if (status == null) return;
mPositionManager.setPosition(readPositionTag, status.id);
}
private void setListShown(boolean shown) {

View File

@ -91,6 +91,7 @@ import org.mariotaku.twidere.menu.SupportAccountActionProvider;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.util.CompareUtils;
import android.support.v7.widget.FixedLinearLayoutManager;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.TransitionUtils;
@ -347,7 +348,8 @@ public class AccountsDashboardFragment extends BaseSupportListFragment implement
mAppMenuSectionView = Utils.newSectionView(context, R.string.more);
mAccountSelectorView = inflater.inflate(R.layout.header_drawer_account_selector, listView, false);
mAccountsSelector = (RecyclerView) mAccountSelectorView.findViewById(R.id.other_accounts_list);
final LinearLayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false);
final LinearLayoutManager layoutManager = new FixedLinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
layoutManager.setStackFromEnd(true);
mAccountsSelector.setLayoutManager(layoutManager);
mAccountsSelector.setAdapter(mAccountsAdapter);

View File

@ -133,7 +133,7 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment<Cursor>
mContentObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
reloadStatuses();
// reloadStatuses();
}
};
cr.registerContentObserver(Accounts.CONTENT_URI, true, mContentObserver);
@ -165,6 +165,11 @@ public abstract class CursorStatusesFragment extends AbsStatusesFragment<Cursor>
return new CursorStatusesAdapter(context, compact);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
getAdapter().setData(null);
}
@Override
public void onLoadMoreContents() {
new TwidereAsyncTask<Void, Void, long[][]>() {

View File

@ -86,6 +86,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.Conversation;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ClipboardUtils;
import android.support.v7.widget.FixedLinearLayoutManager;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.ParseUtils;
import org.mariotaku.twidere.util.TwidereValidator;
@ -237,7 +238,7 @@ public class DirectMessagesConversationFragment extends BaseSupportFragment impl
mTwitterWrapper = getTwitterWrapper();
mValidator = new TwidereValidator(getActivity());
mAdapter = new MessageConversationAdapter(getActivity());
final LinearLayoutManager layoutManager = new LinearLayoutManager(viewContext);
final LinearLayoutManager layoutManager = new FixedLinearLayoutManager(viewContext);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.setStackFromEnd(true);
mMessagesListView.setLayoutManager(layoutManager);

View File

@ -36,6 +36,7 @@ import android.support.v4.content.Loader;
import android.support.v4.util.LongSparseArray;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener;
import android.support.v7.widget.FixedLinearLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
@ -66,7 +67,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import org.mariotaku.twidere.task.TwidereAsyncTask;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ContentListScrollListener;
import org.mariotaku.twidere.util.ContentListScrollListener.ContentListAware;
import org.mariotaku.twidere.util.ContentListScrollListener.ContentListSupport;
import org.mariotaku.twidere.util.MultiSelectManager;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils;
@ -82,7 +83,7 @@ import static org.mariotaku.twidere.util.Utils.openMessageConversation;
public class DirectMessagesFragment extends BaseSupportFragment implements LoaderCallbacks<Cursor>,
RefreshScrollTopInterface, OnRefreshListener, MessageEntriesAdapterListener,
ControlBarOffsetListener, ContentListAware {
ControlBarOffsetListener, ContentListSupport {
private final SupportFragmentReloadCursorObserver mReloadContentObserver = new SupportFragmentReloadCursorObserver(
this, 0, this);
@ -240,7 +241,7 @@ public class DirectMessagesFragment extends BaseSupportFragment implements Loade
mMultiSelectManager = getMultiSelectManager();
mAdapter = new MessageEntriesAdapter(viewContext);
mAdapter.setListener(this);
mLayoutManager = new LinearLayoutManager(viewContext);
mLayoutManager = new FixedLinearLayoutManager(viewContext);
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mSwipeRefreshLayout.setOnRefreshListener(this);
mSwipeRefreshLayout.setColorSchemeColors(ThemeUtils.getUserAccentColor(viewContext));

View File

@ -30,18 +30,13 @@ import org.mariotaku.twidere.util.AsyncTwitterWrapper;
*/
public class HomeTimelineFragment extends CursorStatusesFragment {
public static final String KEY_READ_POSITION_TAG = "home_timeline";
@Override
public Uri getContentUri() {
return Statuses.CONTENT_URI;
}
@Override
protected void updateRefreshState() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null) return;
setRefreshing(twitter.isHomeTimelineRefreshing());
}
@Override
protected int getNotificationType() {
return NOTIFICATION_ID_HOME_TIMELINE;
@ -53,6 +48,13 @@ public class HomeTimelineFragment extends CursorStatusesFragment {
return pref != null && pref.getBoolean(KEY_FILTERS_IN_HOME_TIMELINE, true);
}
@Override
protected void updateRefreshState() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null) return;
setRefreshing(twitter.isHomeTimelineRefreshing());
}
@Override
public int getStatuses(long[] accountIds, long[] maxIds, long[] sinceIds) {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
@ -63,4 +65,8 @@ public class HomeTimelineFragment extends CursorStatusesFragment {
return twitter.getHomeTimelineAsync(accountIds, maxIds, sinceIds);
}
@Override
protected String getReadPositionTag() {
return KEY_READ_POSITION_TAG;
}
}

View File

@ -32,6 +32,8 @@ import org.mariotaku.twidere.util.AsyncTwitterWrapper;
*/
public class MentionsTimelineFragment extends CursorStatusesFragment {
public static final String KEY_READ_POSITION_TAG = "mentions_timeline";
@Override
public Uri getContentUri() {
return Mentions.CONTENT_URI;
@ -44,13 +46,6 @@ public class MentionsTimelineFragment extends CursorStatusesFragment {
return adapter;
}
@Override
protected void updateRefreshState() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null) return;
setRefreshing(twitter.isMentionsTimelineRefreshing());
}
@Override
protected int getNotificationType() {
return NOTIFICATION_ID_MENTIONS_TIMELINE;
@ -62,6 +57,13 @@ public class MentionsTimelineFragment extends CursorStatusesFragment {
return pref != null && pref.getBoolean(KEY_FILTERS_IN_MENTIONS_TIMELINE, true);
}
@Override
protected void updateRefreshState() {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
if (twitter == null) return;
setRefreshing(twitter.isMentionsTimelineRefreshing());
}
@Override
public int getStatuses(long[] accountIds, long[] maxIds, long[] sinceIds) {
final AsyncTwitterWrapper twitter = getTwitterWrapper();
@ -69,4 +71,9 @@ public class MentionsTimelineFragment extends CursorStatusesFragment {
return twitter.getMentionsTimelineAsync(accountIds, maxIds, sinceIds);
}
@Override
protected String getReadPositionTag() {
return KEY_READ_POSITION_TAG;
}
}

View File

@ -35,8 +35,8 @@ import org.mariotaku.twidere.R;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.Utils;
@ -92,7 +92,6 @@ public class RetweetQuoteDialogFragment extends BaseSupportDialogFragment implem
final int profileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
final int mediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
final boolean nameFirst = preferences.getBoolean(KEY_NAME_FIRST, true);
final boolean nicknameOnly = preferences.getBoolean(KEY_NICKNAME_ONLY, false);
final boolean displayMediaPreview = preferences.getBoolean(KEY_MEDIA_PREVIEW, false);
final ParcelableStatus status = getStatus();
@ -103,7 +102,7 @@ public class RetweetQuoteDialogFragment extends BaseSupportDialogFragment implem
builder.setNegativeButton(android.R.string.cancel, null);
holder.displayStatus(context, loader, handler, twitter, displayMediaPreview, true,
true, nameFirst, nicknameOnly, profileImageStyle, mediaPreviewStyle, status, null, true);
true, nameFirst, profileImageStyle, mediaPreviewStyle, status, null, true);
view.findViewById(R.id.item_menu).setVisibility(View.GONE);
view.findViewById(R.id.action_buttons).setVisibility(View.GONE);

View File

@ -44,13 +44,13 @@ import android.support.v4.content.Loader;
import android.support.v4.util.Pair;
import android.support.v7.widget.ActionMenuView;
import android.support.v7.widget.CardView;
import android.support.v7.widget.FixedLinearLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.Adapter;
import android.support.v7.widget.RecyclerView.LayoutParams;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.text.Html;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.LayoutInflater;
@ -87,9 +87,9 @@ import org.mariotaku.twidere.text.method.StatusContentMovementMethod;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.ClipboardUtils;
import org.mariotaku.twidere.util.CompareUtils;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.LinkCreator;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.StatusLinkClickHandler;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.TwidereLinkify;
@ -456,7 +456,7 @@ public class StatusFragment extends BaseSupportFragment
private final MediaLoaderWrapper mImageLoader;
private final ImageLoadingHandler mImageLoadingHandler;
private final boolean mNameFirst, mNicknameOnly;
private final boolean mNameFirst;
private final int mCardLayoutResource;
private final int mTextSize;
private final int mCardBackgroundColor;
@ -483,7 +483,6 @@ public class StatusFragment extends BaseSupportFragment
mImageLoadingHandler = new ImageLoadingHandler(R.id.media_preview_progress);
mCardBackgroundColor = ThemeUtils.getCardBackgroundColor(context);
mNameFirst = preferences.getBoolean(KEY_NAME_FIRST, true);
mNicknameOnly = preferences.getBoolean(KEY_NICKNAME_ONLY, true);
mTextSize = preferences.getInt(KEY_TEXT_SIZE, res.getInteger(R.integer.default_text_size));
mProfileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
mIsCompact = compact;
@ -657,10 +656,6 @@ public class StatusFragment extends BaseSupportFragment
return mNameFirst;
}
public boolean isNicknameOnly() {
return mNicknameOnly;
}
@Override
public void onViewDetachedFromWindow(ViewHolder holder) {
super.onViewDetachedFromWindow(holder);
@ -1112,11 +1107,10 @@ public class StatusFragment extends BaseSupportFragment
final Resources resources = context.getResources();
final MediaLoaderWrapper loader = adapter.getImageLoader();
final boolean nameFirst = adapter.isNameFirst();
final boolean nicknameOnly = adapter.isNicknameOnly();
if (status.retweet_id > 0) {
final String retweetedBy = UserColorNameUtils.getDisplayName(context, status.retweeted_by_id,
status.retweeted_by_name, status.retweeted_by_screen_name, nameFirst, nicknameOnly);
status.retweeted_by_name, status.retweeted_by_screen_name, nameFirst);
retweetedByView.setText(context.getString(R.string.name_retweeted, retweetedBy));
retweetedByContainer.setVisibility(View.VISIBLE);
} else {
@ -1124,15 +1118,7 @@ public class StatusFragment extends BaseSupportFragment
retweetedByContainer.setVisibility(View.GONE);
}
final String nickname = getUserNickname(context, status.user_id, true);
if (TextUtils.isEmpty(nickname)) {
nameView.setText(status.user_name);
} else if (nicknameOnly) {
nameView.setText(nickname);
} else {
nameView.setText(context.getString(R.string.name_with_nickname, status.user_name,
nickname));
}
nameView.setText(getUserNickname(context, status.user_id, status.user_name, true));
screenNameView.setText("@" + status.user_screen_name);
textView.setText(Html.fromHtml(status.text_html));
@ -1240,7 +1226,7 @@ public class StatusFragment extends BaseSupportFragment
}
private static class StatusListLinearLayoutManager extends LinearLayoutManager {
private static class StatusListLinearLayoutManager extends FixedLinearLayoutManager {
private final RecyclerView recyclerView;

View File

@ -41,8 +41,8 @@ import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.SingleResponse;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.view.holder.StatusViewHolder;
@ -136,11 +136,10 @@ public class StatusTranslateDialogFragment extends BaseSupportDialogFragment imp
final int profileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
final int mediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
final boolean nameFirst = preferences.getBoolean(KEY_NAME_FIRST, true);
final boolean nicknameOnly = preferences.getBoolean(KEY_NICKNAME_ONLY, false);
final boolean displayMediaPreview = preferences.getBoolean(KEY_MEDIA_PREVIEW, false);
mHolder.displayStatus(activity, loader, handler, twitter, displayMediaPreview, true,
true, nameFirst, nicknameOnly, profileImageStyle, mediaPreviewStyle, status, null, true);
true, nameFirst, profileImageStyle, mediaPreviewStyle, status, null, true);
mStatusContainer.findViewById(R.id.item_menu).setVisibility(View.GONE);
mStatusContainer.findViewById(R.id.action_buttons).setVisibility(View.GONE);

View File

@ -31,8 +31,8 @@ import org.mariotaku.twidere.R;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.view.holder.StatusViewHolder;
@ -80,7 +80,6 @@ public class ViewStatusDialogFragment extends BaseSupportDialogFragment {
final int profileImageStyle = Utils.getProfileImageStyle(preferences.getString(KEY_PROFILE_IMAGE_STYLE, null));
final int mediaPreviewStyle = Utils.getMediaPreviewStyle(preferences.getString(KEY_MEDIA_PREVIEW_STYLE, null));
final boolean nameFirst = preferences.getBoolean(KEY_NAME_FIRST, true);
final boolean nicknameOnly = preferences.getBoolean(KEY_NICKNAME_ONLY, false);
final boolean displayExtraType = args.getBoolean(EXTRA_SHOW_EXTRA_TYPE, true);
final boolean displayMediaPreview;
if (args.containsKey(EXTRA_SHOW_MEDIA_PREVIEW)) {
@ -89,8 +88,7 @@ public class ViewStatusDialogFragment extends BaseSupportDialogFragment {
displayMediaPreview = preferences.getBoolean(KEY_MEDIA_PREVIEW, false);
}
mHolder.displayStatus(activity, loader, handler, twitter, displayMediaPreview, true,
true, nameFirst, nicknameOnly, profileImageStyle, mediaPreviewStyle, status, null,
displayExtraType);
true, nameFirst, profileImageStyle, mediaPreviewStyle, status, null, displayExtraType);
mStatusContainer.findViewById(R.id.item_menu).setVisibility(View.GONE);
mStatusContainer.findViewById(R.id.action_buttons).setVisibility(View.GONE);
}

View File

@ -47,8 +47,8 @@ import org.mariotaku.twidere.R;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.task.TwidereAsyncTask;
import org.mariotaku.twidere.util.BitmapUtils;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.Utils;
import java.util.List;
@ -136,7 +136,7 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
@Override
public void onLoadingComplete(final String imageUri, final View view, final Bitmap loadedImage) {
final Bitmap roundedBitmap = Utils.getCircleBitmap(loadedImage);
final Bitmap roundedBitmap = BitmapUtils.getCircleBitmap(loadedImage);
setIcon(new BitmapDrawable(getContext().getResources(), roundedBitmap));
}

View File

@ -39,6 +39,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
@ -47,13 +48,15 @@ import android.os.Looper;
import android.os.ParcelFileDescriptor;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat;
import android.text.Html;
import android.support.v4.app.NotificationCompat.InboxStyle;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.StyleSpan;
import android.util.Log;
import com.squareup.otto.Bus;
import org.apache.commons.lang3.ArrayUtils;
import org.mariotaku.jsonserializer.JSONFileIO;
import org.mariotaku.querybuilder.Columns.Column;
import org.mariotaku.querybuilder.Expression;
import org.mariotaku.querybuilder.RawItemArray;
@ -62,27 +65,27 @@ import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.support.HomeActivity;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.fragment.support.HomeTimelineFragment;
import org.mariotaku.twidere.fragment.support.MentionsTimelineFragment;
import org.mariotaku.twidere.model.AccountPreferences;
import org.mariotaku.twidere.model.ParcelableDirectMessage;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.SupportTabSpec;
import org.mariotaku.twidere.model.UnreadItem;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
import org.mariotaku.twidere.provider.TwidereDataStore.Mentions;
import org.mariotaku.twidere.provider.TwidereDataStore.Preferences;
import org.mariotaku.twidere.provider.TwidereDataStore.SearchHistory;
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
import org.mariotaku.twidere.provider.TwidereDataStore.UnreadCounts;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.CustomTabUtils;
import org.mariotaku.twidere.util.HtmlEscapeHelper;
import org.mariotaku.twidere.util.ImagePreloader;
import org.mariotaku.twidere.util.MediaPreviewUtils;
import org.mariotaku.twidere.util.ParseUtils;
import org.mariotaku.twidere.util.PermissionsManager;
import org.mariotaku.twidere.util.PositionManager;
import org.mariotaku.twidere.util.SQLiteDatabaseWrapper;
import org.mariotaku.twidere.util.SQLiteDatabaseWrapper.LazyLoadCallback;
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
@ -91,66 +94,44 @@ import org.mariotaku.twidere.util.TwidereQueryBuilder.CachedUsersQueryBuilder;
import org.mariotaku.twidere.util.TwidereQueryBuilder.ConversationQueryBuilder;
import org.mariotaku.twidere.util.UserColorNameUtils;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.collection.NoDuplicatesCopyOnWriteArrayList;
import org.mariotaku.twidere.util.message.UnreadCountUpdatedEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import twitter4j.http.HostAddressResolver;
import static org.mariotaku.twidere.util.Utils.clearAccountColor;
import static org.mariotaku.twidere.util.Utils.clearAccountName;
import static org.mariotaku.twidere.util.Utils.getAccountDisplayName;
import static org.mariotaku.twidere.util.Utils.getAccountIds;
import static org.mariotaku.twidere.util.Utils.getAccountNotificationId;
import static org.mariotaku.twidere.util.Utils.getAccountScreenName;
import static org.mariotaku.twidere.util.Utils.getActivatedAccountIds;
import static org.mariotaku.twidere.util.Utils.getNotificationUri;
import static org.mariotaku.twidere.util.Utils.getTableId;
import static org.mariotaku.twidere.util.Utils.getTableNameById;
import static org.mariotaku.twidere.util.Utils.isFiltered;
import static org.mariotaku.twidere.util.Utils.isNotificationsSilent;
public final class TwidereDataProvider extends ContentProvider implements Constants, OnSharedPreferenceChangeListener,
LazyLoadCallback {
private static final String UNREAD_STATUSES_FILE_NAME = "unread_statuses";
private static final String UNREAD_MENTIONS_FILE_NAME = "unread_mentions";
private static final String UNREAD_MESSAGES_FILE_NAME = "unread_messages";
private ContentResolver mContentResolver;
private SQLiteDatabaseWrapper mDatabaseWrapper;
private PermissionsManager mPermissionsManager;
private NotificationManager mNotificationManager;
private PositionManager mPositionManager;
private SharedPreferencesWrapper mPreferences;
private ImagePreloader mImagePreloader;
private HostAddressResolver mHostAddressResolver;
private Handler mHandler;
private final List<ParcelableStatus> mNewStatuses = new CopyOnWriteArrayList<>();
private final List<ParcelableStatus> mNewMentions = new CopyOnWriteArrayList<>();
private final List<ParcelableDirectMessage> mNewMessages = new CopyOnWriteArrayList<>();
private final List<UnreadItem> mUnreadStatuses = new NoDuplicatesCopyOnWriteArrayList<>();
private final List<UnreadItem> mUnreadMentions = new NoDuplicatesCopyOnWriteArrayList<>();
private final List<UnreadItem> mUnreadMessages = new NoDuplicatesCopyOnWriteArrayList<>();
private boolean mHomeActivityInBackground;
private boolean mNameFirst, mNickOnly;
private boolean mNameFirst;
private final BroadcastReceiver mHomeActivityStateReceiver = new BroadcastReceiver() {
@Override
@ -247,15 +228,6 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
return 1;
}
case VIRTUAL_TABLE_ID_UNREAD_COUNTS: {
final List<String> segments = uri.getPathSegments();
final int segmentsSize = segments.size();
if (segmentsSize == 1)
return clearUnreadCount();
else if (segmentsSize == 2)
return clearUnreadCount(ParseUtils.parseInt(segments.get(1)));
else if (segmentsSize == 4)
return removeUnreadItems(ParseUtils.parseInt(segments.get(1)),
ParseUtils.parseLong(segments.get(2)), TwidereArrayUtils.parseLongArray(segments.get(3), ','));
return 0;
}
}
@ -348,12 +320,12 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
mPreferences.registerOnSharedPreferenceChangeListener(this);
updatePreferences();
mPermissionsManager = new PermissionsManager(context);
mPositionManager = new PositionManager(context);
mImagePreloader = new ImagePreloader(context, app.getImageLoader());
final IntentFilter filter = new IntentFilter();
filter.addAction(BROADCAST_HOME_ACTIVITY_ONSTART);
filter.addAction(BROADCAST_HOME_ACTIVITY_ONSTOP);
context.registerReceiver(mHomeActivityStateReceiver, filter);
restoreUnreadItems();
// final GetWritableDatabaseTask task = new
// GetWritableDatabaseTask(context, helper, mDatabaseWrapper);
// task.executeTask();
@ -681,260 +653,11 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
}
private void clearNotification() {
mNewStatuses.clear();
mNewMentions.clear();
mNewMessages.clear();
getNotificationManager().cancelAll();
}
private void clearNotification(final int notificationType, final long accountId) {
final NotificationManager nm = getNotificationManager();
final boolean isAccountSpecific;
switch (notificationType) {
case NOTIFICATION_ID_HOME_TIMELINE: {
mNewStatuses.clear();
isAccountSpecific = true;
break;
}
case NOTIFICATION_ID_MENTIONS_TIMELINE: {
mNewMentions.clear();
isAccountSpecific = true;
break;
}
case NOTIFICATION_ID_DIRECT_MESSAGES: {
mNewMessages.clear();
isAccountSpecific = true;
break;
}
default: {
isAccountSpecific = false;
}
}
if (isAccountSpecific) {
if (accountId > 0) {
nm.cancel(getAccountNotificationId(notificationType, accountId));
} else {
for (final long id : getAccountIds(getContext())) {
nm.cancel(getAccountNotificationId(notificationType, id));
}
}
} else {
nm.cancel(notificationType);
}
}
private int clearUnreadCount() {
int result = 0;
result += mUnreadStatuses.size();
result += mUnreadMentions.size();
result += mUnreadMentions.size();
mUnreadStatuses.clear();
mUnreadMentions.clear();
mUnreadMessages.clear();
saveUnreadItemsFile(mUnreadStatuses, UNREAD_STATUSES_FILE_NAME);
saveUnreadItemsFile(mUnreadMentions, UNREAD_MENTIONS_FILE_NAME);
saveUnreadItemsFile(mUnreadMessages, UNREAD_MESSAGES_FILE_NAME);
notifyContentObserver(UnreadCounts.CONTENT_URI);
return result;
}
private int clearUnreadCount(final int position) {
final Context context = getContext();
final int result;
final SupportTabSpec tab = CustomTabUtils.getAddedTabAt(context, position);
final String type = tab.type;
if (TAB_TYPE_HOME_TIMELINE.equals(type) || TAB_TYPE_STAGGERED_HOME_TIMELINE.equals(type)) {
final long account_id = tab.args != null ? tab.args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
final long[] account_ids = account_id > 0 ? new long[]{account_id} : getActivatedAccountIds(context);
result = clearUnreadCount(mUnreadStatuses, account_ids);
saveUnreadItemsFile(mUnreadStatuses, UNREAD_STATUSES_FILE_NAME);
} else if (TAB_TYPE_MENTIONS_TIMELINE.equals(type)) {
final long account_id = tab.args != null ? tab.args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
final long[] account_ids = account_id > 0 ? new long[]{account_id} : getActivatedAccountIds(context);
result = clearUnreadCount(mUnreadMentions, account_ids);
mUnreadMentions.clear();
saveUnreadItemsFile(mUnreadMentions, UNREAD_MENTIONS_FILE_NAME);
} else if (TAB_TYPE_DIRECT_MESSAGES.equals(type)) {
final long account_id = tab.args != null ? tab.args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
final long[] account_ids = account_id > 0 ? new long[]{account_id} : getActivatedAccountIds(context);
result = clearUnreadCount(mUnreadMessages, account_ids);
mUnreadMessages.clear();
saveUnreadItemsFile(mUnreadMessages, UNREAD_MESSAGES_FILE_NAME);
} else
return 0;
if (result > 0) {
notifyUnreadCountChanged(position);
}
return result;
}
private void displayMessagesNotification(final int notifiedCount, final AccountPreferences accountPrefs,
final int notificationType, final int icon, final List<ParcelableDirectMessage> messages) {
final NotificationManager nm = getNotificationManager();
if (notifiedCount == 0 || accountPrefs == null || messages.isEmpty()) return;
final long accountId = accountPrefs.getAccountId();
final Context context = getContext();
final Resources resources = context.getResources();
final NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(context);
notifBuilder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
final ParcelableDirectMessage firstItem = messages.get(0);
final int messagesCount = messages.size();
final Intent deleteIntent = new Intent(BROADCAST_NOTIFICATION_DELETED);
deleteIntent.putExtra(EXTRA_NOTIFICATION_ID, NOTIFICATION_ID_DIRECT_MESSAGES);
deleteIntent.putExtra(EXTRA_NOTIFICATION_ACCOUNT, accountId);
final Intent contentIntent;
final String title;
if (messagesCount > 1) {
notifBuilder.setNumber(messagesCount);
}
final int usersCount = getSendersCount(messages);
contentIntent = new Intent(context, HomeActivity.class);
contentIntent.setAction(Intent.ACTION_MAIN);
contentIntent.addCategory(Intent.CATEGORY_LAUNCHER);
contentIntent.putExtra(EXTRA_TAB_TYPE, TAB_TYPE_DIRECT_MESSAGES);
if (messagesCount == 1) {
final Uri.Builder uriBuilder = new Uri.Builder();
uriBuilder.scheme(SCHEME_TWIDERE);
uriBuilder.authority(AUTHORITY_DIRECT_MESSAGES_CONVERSATION);
uriBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(firstItem.account_id));
uriBuilder.appendQueryParameter(QUERY_PARAM_RECIPIENT_ID, String.valueOf(firstItem.sender_id));
final Intent statusIntent = new Intent(Intent.ACTION_VIEW, uriBuilder.build());
statusIntent.setExtrasClassLoader(context.getClassLoader());
contentIntent.putExtra(EXTRA_EXTRA_INTENT, statusIntent);
}
final String displayName = UserColorNameUtils.getDisplayName(context, firstItem.sender_id, firstItem.sender_name,
firstItem.sender_screen_name, mNameFirst, mNickOnly);
if (usersCount > 1) {
title = resources.getString(R.string.notification_direct_message_multiple_users, displayName,
usersCount - 1, messagesCount);
} else if (messagesCount > 1) {
title = resources.getString(R.string.notification_direct_message_multiple_messages, displayName,
messagesCount);
} else {
title = resources.getString(R.string.notification_direct_message, displayName);
}
notifBuilder.setLargeIcon(getProfileImageForNotification(firstItem.sender_profile_image_url));
buildNotification(notifBuilder, accountPrefs, notificationType, title, title, firstItem.text_plain,
firstItem.timestamp, R.drawable.ic_stat_direct_message, null, contentIntent, deleteIntent);
final NotificationCompat.Style notifStyle;
if (messagesCount > 1) {
final NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(notifBuilder);
final int max = Math.min(4, messagesCount);
for (int i = 0; i < max; i++) {
final ParcelableDirectMessage item = messages.get(i);
if (item == null) return;
final String nameEscaped = HtmlEscapeHelper.escape(UserColorNameUtils.getDisplayName(context, item.sender_id,
item.sender_name, item.sender_name, mNameFirst, mNickOnly));
final String textEscaped = HtmlEscapeHelper.escape(stripMentionText(item.text_unescaped,
getAccountScreenName(context, item.account_id)));
inboxStyle.addLine(Html.fromHtml(String.format("<b>%s</b>: %s", nameEscaped, textEscaped)));
}
if (max == 4 && messagesCount - max > 0) {
inboxStyle.addLine(context.getString(R.string.and_more, messagesCount - max));
}
inboxStyle.setSummaryText(getAccountDisplayName(context, accountId, mNameFirst));
notifStyle = inboxStyle;
} else {
final NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(notifBuilder);
bigTextStyle.bigText(firstItem.text_unescaped);
bigTextStyle.setSummaryText(getAccountDisplayName(context, accountId, mNameFirst));
notifStyle = bigTextStyle;
}
final int accountNotificationId = getAccountNotificationId(NOTIFICATION_ID_DIRECT_MESSAGES, accountId);
nm.notify(accountNotificationId, notifStyle.build());
}
private void displayStatusesNotification(final int notifiedCount, final AccountPreferences accountPreferences,
final int notificationType, final int notificationId, final List<ParcelableStatus> statuses,
final int titleSingle, final int titleMultiple, final int icon) {
final NotificationManager nm = getNotificationManager();
if (notifiedCount == 0 || accountPreferences == null || statuses.isEmpty()) return;
final long accountId = accountPreferences.getAccountId();
final Context context = getContext();
final Resources resources = context.getResources();
final NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(context);
final ParcelableStatus firstItem = statuses.get(0);
final int statusesSize = statuses.size();
final Intent deleteIntent = new Intent(BROADCAST_NOTIFICATION_DELETED);
deleteIntent.putExtra(EXTRA_NOTIFICATION_ID, notificationId);
deleteIntent.putExtra(EXTRA_NOTIFICATION_ACCOUNT, accountId);
final Intent contentIntent;
final String title;
if (statusesSize > 1) {
notifBuilder.setNumber(statusesSize);
}
final int usersCount = getUsersCount(statuses);
contentIntent = new Intent(context, HomeActivity.class);
contentIntent.setAction(Intent.ACTION_MAIN);
contentIntent.addCategory(Intent.CATEGORY_LAUNCHER);
contentIntent.putExtra(EXTRA_TAB_TYPE, TAB_TYPE_MENTIONS_TIMELINE);
if (statusesSize == 1) {
final Uri.Builder uriBuilder = new Uri.Builder();
uriBuilder.scheme(SCHEME_TWIDERE);
uriBuilder.authority(AUTHORITY_STATUS);
uriBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(firstItem.account_id));
uriBuilder.appendQueryParameter(QUERY_PARAM_STATUS_ID, String.valueOf(firstItem.id));
final Intent statusIntent = new Intent(Intent.ACTION_VIEW, uriBuilder.build());
statusIntent.setExtrasClassLoader(context.getClassLoader());
statusIntent.putExtra(EXTRA_STATUS, firstItem);
contentIntent.putExtra(EXTRA_EXTRA_INTENT, statusIntent);
}
final String displayName = UserColorNameUtils.getDisplayName(context, firstItem.user_id, firstItem.user_name,
firstItem.user_screen_name, mNameFirst, mNickOnly);
if (usersCount > 1) {
title = resources.getString(titleMultiple, displayName, usersCount - 1);
} else {
title = resources.getString(titleSingle, displayName);
}
notifBuilder.setLargeIcon(getProfileImageForNotification(firstItem.user_profile_image_url));
buildNotification(notifBuilder, accountPreferences, notificationType, title, title, firstItem.text_plain,
firstItem.timestamp, icon, null, contentIntent, deleteIntent);
final NotificationCompat.Style notifStyle;
if (statusesSize > 1) {
final NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(notifBuilder);
final int max = Math.min(4, statusesSize);
for (int i = 0; i < max; i++) {
final ParcelableStatus s = safeGet(statuses, i);
if (s == null) return;
final String nameEscaped = HtmlEscapeHelper.escape(UserColorNameUtils.getDisplayName(context, s.user_id, s.user_name,
s.user_screen_name, mNameFirst, mNickOnly));
final String textEscaped = HtmlEscapeHelper.escape(stripMentionText(s.text_unescaped,
getAccountScreenName(context, s.account_id)));
inboxStyle.addLine(Html.fromHtml(String.format("<b>%s</b>: %s", nameEscaped, textEscaped)));
}
if (max == 4 && statusesSize - max > 0) {
inboxStyle.addLine(context.getString(R.string.and_more, statusesSize - max));
}
inboxStyle.setSummaryText(getAccountDisplayName(context, accountId, mNameFirst));
notifStyle = inboxStyle;
} else {
final Intent replyIntent = new Intent(INTENT_ACTION_REPLY);
replyIntent.setExtrasClassLoader(context.getClassLoader());
replyIntent.putExtra(EXTRA_NOTIFICATION_ID, notificationType);
replyIntent.putExtra(EXTRA_NOTIFICATION_ACCOUNT, accountId);
replyIntent.putExtra(EXTRA_STATUS, firstItem);
replyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final Uri.Builder viewProfileBuilder = new Uri.Builder();
viewProfileBuilder.scheme(SCHEME_TWIDERE);
viewProfileBuilder.authority(AUTHORITY_USER);
viewProfileBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(firstItem.account_id));
viewProfileBuilder.appendQueryParameter(QUERY_PARAM_USER_ID, String.valueOf(firstItem.user_id));
final Intent viewProfileIntent = new Intent(Intent.ACTION_VIEW, viewProfileBuilder.build());
viewProfileIntent.setPackage(APP_PACKAGE_NAME);
notifBuilder.addAction(R.drawable.ic_action_reply, context.getString(R.string.reply),
PendingIntent.getActivity(context, 0, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT));
notifBuilder.addAction(R.drawable.ic_action_profile, context.getString(R.string.profile),
PendingIntent.getActivity(context, 0, viewProfileIntent, PendingIntent.FLAG_UPDATE_CURRENT));
final NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle(notifBuilder);
bigTextStyle.bigText(stripMentionText(firstItem.text_unescaped,
getAccountScreenName(context, firstItem.account_id)));
bigTextStyle.setSummaryText(getAccountDisplayName(context, accountId, mNameFirst));
notifStyle = bigTextStyle;
}
final int accountNotificationId = getAccountNotificationId(notificationId, accountId);
nm.notify(accountNotificationId, notifStyle.build());
}
private Cursor getCachedImageCursor(final String url) {
@ -996,21 +719,11 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
private Cursor getNotificationsCursor() {
final MatrixCursor c = new MatrixCursor(TwidereDataStore.Notifications.MATRIX_COLUMNS);
c.addRow(new Integer[]{NOTIFICATION_ID_HOME_TIMELINE, mUnreadStatuses.size()});
c.addRow(new Integer[]{NOTIFICATION_ID_MENTIONS_TIMELINE, mNewMentions.size()});
c.addRow(new Integer[]{NOTIFICATION_ID_DIRECT_MESSAGES, mNewMessages.size()});
return c;
}
private Cursor getNotificationsCursor(final int id) {
final MatrixCursor c = new MatrixCursor(TwidereDataStore.Notifications.MATRIX_COLUMNS);
if (id == NOTIFICATION_ID_HOME_TIMELINE) {
c.addRow(new Integer[]{id, mNewStatuses.size()});
} else if (id == NOTIFICATION_ID_MENTIONS_TIMELINE) {
c.addRow(new Integer[]{id, mNewMentions.size()});
} else if (id == NOTIFICATION_ID_DIRECT_MESSAGES) {
c.addRow(new Integer[]{id, mNewMessages.size()});
}
return c;
}
@ -1026,15 +739,6 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
return Bitmap.createScaledBitmap(BitmapFactory.decodeResource(res, R.mipmap.ic_launcher), w, h, true);
}
private int getSendersCount(final List<ParcelableDirectMessage> items) {
if (items == null || items.isEmpty()) return 0;
final Set<Long> ids = new HashSet<>();
for (final ParcelableDirectMessage item : items.toArray(new ParcelableDirectMessage[items.size()])) {
ids.add(item.sender_id);
}
return ids.size();
}
private Cursor getUnreadCountsCursor() {
final MatrixCursor c = new MatrixCursor(TwidereDataStore.UnreadCounts.MATRIX_COLUMNS);
return c;
@ -1042,46 +746,12 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
private Cursor getUnreadCountsCursor(final int position) {
final MatrixCursor c = new MatrixCursor(TwidereDataStore.UnreadCounts.MATRIX_COLUMNS);
final Context context = getContext();
final SupportTabSpec tab = CustomTabUtils.getAddedTabAt(context, position);
if (tab == null) return c;
final int count;
if (TAB_TYPE_HOME_TIMELINE.equals(tab.type) || TAB_TYPE_STAGGERED_HOME_TIMELINE.equals(tab.type)) {
final long account_id = tab.args != null ? tab.args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
final long[] account_ids = account_id > 0 ? new long[]{account_id} : getActivatedAccountIds(context);
count = getUnreadCount(mUnreadStatuses, account_ids);
} else if (TAB_TYPE_MENTIONS_TIMELINE.equals(tab.type)) {
final long account_id = tab.args != null ? tab.args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
final long[] account_ids = account_id > 0 ? new long[]{account_id} : getActivatedAccountIds(context);
count = getUnreadCount(mUnreadMentions, account_ids);
} else if (TAB_TYPE_DIRECT_MESSAGES.equals(tab.type)) {
final long account_id = tab.args != null ? tab.args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
final long[] account_ids = account_id > 0 ? new long[]{account_id} : getActivatedAccountIds(context);
count = getUnreadCount(mUnreadMessages, account_ids);
} else {
count = 0;
}
if (tab.type != null) {
c.addRow(new Object[]{position, tab.type, count});
}
return c;
}
private Cursor getUnreadCountsCursorByType(final String type) {
final MatrixCursor c = new MatrixCursor(TwidereDataStore.UnreadCounts.MATRIX_COLUMNS);
final int count;
if (TAB_TYPE_HOME_TIMELINE.equals(type) || TAB_TYPE_STAGGERED_HOME_TIMELINE.equals(type)) {
count = mUnreadStatuses.size();
} else if (TAB_TYPE_MENTIONS_TIMELINE.equals(type)) {
count = mUnreadMentions.size();
} else if (TAB_TYPE_DIRECT_MESSAGES.equals(type)) {
count = mUnreadMessages.size();
} else {
count = 0;
}
if (type != null) {
c.addRow(new Object[]{-1, type, count});
}
return c;
}
@ -1104,67 +774,6 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
cr.notifyChange(uri, null);
}
private int notifyIncomingMessagesInserted(final ContentValues... values) {
if (values == null || values.length == 0) return 0;
// Add statuses that not filtered to list for future use.
int result = 0;
for (final ContentValues value : values) {
final ParcelableDirectMessage message = new ParcelableDirectMessage(value);
mNewMessages.add(message);
if (mUnreadMessages.add(new UnreadItem(message.sender_id, message.account_id))) {
result++;
}
}
if (result > 0) {
saveUnreadItemsFile(mUnreadMessages, UNREAD_MESSAGES_FILE_NAME);
}
return result;
}
private int notifyMentionsInserted(final AccountPreferences[] prefs, final ContentValues... values) {
if (values == null || values.length == 0) return 0;
// Add statuses that not filtered to list for future use.
int result = 0;
final boolean enabled = mPreferences.getBoolean(KEY_FILTERS_IN_MENTIONS_TIMELINE, true);
final boolean filtersForRts = mPreferences.getBoolean(KEY_FILTERS_FOR_RTS, true);
for (final ContentValues value : values) {
final ParcelableStatus status = new ParcelableStatus(value);
if (!enabled || !isFiltered(mDatabaseWrapper.getSQLiteDatabase(), status, filtersForRts)) {
final AccountPreferences pref = AccountPreferences.getAccountPreferences(prefs, status.account_id);
if (pref == null || status.user_is_following || !pref.isNotificationFollowingOnly()) {
mNewMentions.add(status);
}
if (mUnreadMentions.add(new UnreadItem(status.id, status.account_id))) {
result++;
}
}
}
if (result > 0) {
saveUnreadItemsFile(mUnreadMentions, UNREAD_MENTIONS_FILE_NAME);
}
return result;
}
private int notifyStatusesInserted(final ContentValues... values) {
if (values == null || values.length == 0) return 0;
// Add statuses that not filtered to list for future use.
int result = 0;
final boolean enabled = mPreferences.getBoolean(KEY_FILTERS_IN_HOME_TIMELINE, true);
final boolean filtersForRts = mPreferences.getBoolean(KEY_FILTERS_FOR_RTS, true);
for (final ContentValues value : values) {
final ParcelableStatus status = new ParcelableStatus(value);
if (!enabled || !isFiltered(mDatabaseWrapper.getSQLiteDatabase(), status, filtersForRts)) {
mNewStatuses.add(status);
if (mUnreadStatuses.add(new UnreadItem(status.id, status.account_id))) {
result++;
}
}
}
if (result > 0) {
saveUnreadItemsFile(mUnreadStatuses, UNREAD_STATUSES_FILE_NAME);
}
return result;
}
private void notifyUnreadCountChanged(final int position) {
final Context context = getContext();
@ -1202,19 +811,11 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
if (!uri.getBooleanQueryParameter(QUERY_PARAM_NOTIFY, true)) return;
switch (tableId) {
case TABLE_ID_STATUSES: {
final int notifiedCount = notifyStatusesInserted(valuesArray);
final List<ParcelableStatus> items = new ArrayList<>(mNewStatuses);
Collections.sort(items);
final AccountPreferences[] prefs = AccountPreferences.getNotificationEnabledPreferences(getContext(),
getAccountIds(getContext()));
for (final AccountPreferences pref : prefs) {
if (pref.isHomeTimelineNotificationEnabled()) {
final long accountId = pref.getAccountId();
displayStatusesNotification(notifiedCount, pref, pref.getHomeTimelineNotificationType(),
NOTIFICATION_ID_HOME_TIMELINE, getStatusesForAccounts(items, accountId),
R.string.notification_status, R.string.notification_status_multiple,
R.drawable.ic_stat_twitter);
}
if (!pref.isHomeTimelineNotificationEnabled()) continue;
showTimelineNotification(pref, mPositionManager.getPosition(HomeTimelineFragment.KEY_READ_POSITION_TAG));
}
notifyUnreadCountChanged(NOTIFICATION_ID_HOME_TIMELINE);
break;
@ -1222,32 +823,19 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
case TABLE_ID_MENTIONS: {
final AccountPreferences[] prefs = AccountPreferences.getNotificationEnabledPreferences(getContext(),
getAccountIds(getContext()));
final int notifiedCount = notifyMentionsInserted(prefs, valuesArray);
final List<ParcelableStatus> items = new ArrayList<>(mNewMentions);
Collections.sort(items);
for (final AccountPreferences pref : prefs) {
if (pref.isMentionsNotificationEnabled()) {
final long accountId = pref.getAccountId();
displayStatusesNotification(notifiedCount, pref, pref.getMentionsNotificationType(),
NOTIFICATION_ID_MENTIONS_TIMELINE, getStatusesForAccounts(items, accountId),
R.string.notification_mention, R.string.notification_mention_multiple,
R.drawable.ic_stat_mention);
}
if (!pref.isMentionsNotificationEnabled()) continue;
showMentionsNotification(pref, mPositionManager.getPosition(MentionsTimelineFragment.KEY_READ_POSITION_TAG));
}
notifyUnreadCountChanged(NOTIFICATION_ID_MENTIONS_TIMELINE);
break;
}
case TABLE_ID_DIRECT_MESSAGES_INBOX: {
final int notifiedCount = notifyIncomingMessagesInserted(valuesArray);
final List<ParcelableDirectMessage> items = new ArrayList<>(mNewMessages);
Collections.sort(items);
final AccountPreferences[] prefs = AccountPreferences.getNotificationEnabledPreferences(getContext(),
getAccountIds(getContext()));
for (final AccountPreferences pref : prefs) {
if (pref.isDirectMessagesNotificationEnabled()) {
final long accountId = pref.getAccountId();
displayMessagesNotification(notifiedCount, pref, pref.getDirectMessagesNotificationType(),
R.drawable.ic_stat_mention, getMessagesForAccounts(items, accountId));
}
}
notifyUnreadCountChanged(NOTIFICATION_ID_DIRECT_MESSAGES);
@ -1259,6 +847,158 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
}
}
private void showTimelineNotification(AccountPreferences pref, long position) {
final long accountId = pref.getAccountId();
final Context context = getContext();
final Resources resources = context.getResources();
final NotificationManager nm = getNotificationManager();
final Expression selection = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, accountId),
Expression.greaterThan(Statuses.STATUS_ID, position));
final String filteredSelection = Utils.buildStatusFilterWhereClause(Statuses.TABLE_NAME,
selection, true).getSQL();
final String[] userProjection = {Statuses.USER_ID, Statuses.USER_NAME, Statuses.USER_SCREEN_NAME};
final String[] statusProjection = new String[0];
final Cursor statusCursor = mDatabaseWrapper.query(Statuses.TABLE_NAME, statusProjection,
filteredSelection, null, null, null, Statuses.SORT_ORDER_TIMESTAMP_DESC);
final Cursor userCursor = mDatabaseWrapper.query(Statuses.TABLE_NAME, userProjection,
filteredSelection, null, Statuses.USER_ID, null, Statuses.SORT_ORDER_TIMESTAMP_DESC);
try {
final int usersCount = userCursor.getCount();
final int statusesCount = statusCursor.getCount();
if (statusesCount == 0 || usersCount == 0) return;
final int idxUserName = userCursor.getColumnIndex(Statuses.USER_NAME),
idxUserScreenName = userCursor.getColumnIndex(Statuses.USER_NAME),
idxUserId = userCursor.getColumnIndex(Statuses.USER_NAME);
final String notificationTitle = resources.getQuantityString(R.plurals.N_new_statuses,
statusesCount, statusesCount);
final String notificationContent;
userCursor.moveToFirst();
final String displayName = UserColorNameUtils.getUserNickname(context, userCursor.getLong(idxUserId),
mNameFirst ? userCursor.getString(idxUserName) : userCursor.getString(idxUserScreenName));
if (usersCount == 1) {
notificationContent = context.getString(R.string.from_name, displayName);
} else if (usersCount == 2) {
userCursor.moveToPosition(1);
final String othersName = UserColorNameUtils.getUserNickname(context, userCursor.getLong(idxUserId),
mNameFirst ? userCursor.getString(idxUserName) : userCursor.getString(idxUserScreenName));
notificationContent = resources.getQuantityString(R.plurals.from_name_and_N_others,
usersCount - 1, othersName, usersCount - 1);
} else {
userCursor.moveToPosition(1);
final String othersName = UserColorNameUtils.getUserNickname(context, userCursor.getLong(idxUserId),
mNameFirst ? userCursor.getString(idxUserName) : userCursor.getString(idxUserScreenName));
notificationContent = resources.getString(R.string.from_name_and_N_others, othersName, usersCount - 1);
}
// Setup on click intent
final Intent homeIntent = new Intent(context, HomeActivity.class);
final PendingIntent clickIntent = PendingIntent.getActivity(context, 0, homeIntent, 0);
// Setup notification
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setSmallIcon(R.drawable.ic_stat_twitter);
builder.setTicker(notificationTitle);
builder.setContentTitle(notificationTitle);
builder.setContentText(notificationContent);
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
builder.setContentIntent(clickIntent);
builder.setNumber(statusesCount);
builder.setColor(pref.getNotificationLightColor());
nm.notify("home_" + accountId, NOTIFICATION_ID_HOME_TIMELINE, builder.build());
} finally {
statusCursor.close();
userCursor.close();
}
}
private void showMentionsNotification(AccountPreferences pref, long position) {
final long accountId = pref.getAccountId();
final Context context = getContext();
final Resources resources = context.getResources();
final NotificationManager nm = getNotificationManager();
final Expression selection = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, accountId),
Expression.greaterThan(Statuses.STATUS_ID, position));
final String filteredSelection = Utils.buildStatusFilterWhereClause(Mentions.TABLE_NAME,
selection, true).getSQL();
final String[] userProjection = {Statuses.USER_ID, Statuses.USER_NAME, Statuses.USER_SCREEN_NAME};
final String[] statusProjection = {Statuses.USER_ID, Statuses.USER_NAME, Statuses.USER_SCREEN_NAME,
Statuses.TEXT_UNESCAPED, Statuses.STATUS_TIMESTAMP};
final Cursor statusCursor = mDatabaseWrapper.query(Mentions.TABLE_NAME, statusProjection,
filteredSelection, null, null, null, Statuses.SORT_ORDER_TIMESTAMP_DESC);
final Cursor userCursor = mDatabaseWrapper.query(Mentions.TABLE_NAME, userProjection,
filteredSelection, null, Statuses.USER_ID, null, Statuses.SORT_ORDER_TIMESTAMP_DESC);
try {
final int usersCount = userCursor.getCount();
final int statusesCount = statusCursor.getCount();
if (statusesCount == 0 || usersCount == 0) return;
final String accountName = Utils.getAccountName(context, accountId);
final String accountScreenName = Utils.getAccountScreenName(context, accountId);
final int idxStatusText = statusCursor.getColumnIndex(Statuses.TEXT_UNESCAPED),
idxStatusTimestamp = statusCursor.getColumnIndex(Statuses.STATUS_TIMESTAMP),
idxStatusUserName = statusCursor.getColumnIndex(Statuses.USER_NAME),
idxStatusUserScreenName = statusCursor.getColumnIndex(Statuses.USER_SCREEN_NAME),
idxUserName = userCursor.getColumnIndex(Statuses.USER_NAME),
idxUserScreenName = userCursor.getColumnIndex(Statuses.USER_NAME),
idxUserId = userCursor.getColumnIndex(Statuses.USER_NAME);
final CharSequence notificationTitle = resources.getQuantityString(R.plurals.N_new_mentions,
statusesCount, statusesCount);
final String notificationContent;
userCursor.moveToFirst();
final String displayName = UserColorNameUtils.getUserNickname(context, userCursor.getLong(idxUserId),
mNameFirst ? userCursor.getString(idxUserName) : userCursor.getString(idxUserScreenName));
if (usersCount == 1) {
notificationContent = context.getString(R.string.notification_mention, displayName);
} else {
notificationContent = context.getString(R.string.notification_mention_multiple,
displayName, usersCount - 1);
}
// Add rich notification and get latest tweet timestamp
long when = -1;
final InboxStyle style = new InboxStyle();
for (int i = 0, j = Math.min(statusesCount, 5); statusCursor.moveToPosition(i) && i < j; i++) {
if (when < 0) {
when = statusCursor.getLong(idxStatusTimestamp);
}
final SpannableStringBuilder sb = new SpannableStringBuilder();
sb.append(UserColorNameUtils.getUserNickname(context, statusCursor.getLong(idxUserId),
mNameFirst ? statusCursor.getString(idxStatusUserName) : statusCursor.getString(idxStatusUserScreenName)));
sb.setSpan(new StyleSpan(Typeface.BOLD), 0, sb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
sb.append(' ');
sb.append(statusCursor.getString(idxStatusText));
style.addLine(sb);
}
if (mNameFirst) {
style.setSummaryText(accountName);
} else {
style.setSummaryText("@" + accountScreenName);
}
// Setup on click intent
final Intent homeIntent = new Intent(context, HomeActivity.class);
final PendingIntent clickIntent = PendingIntent.getActivity(context, 0, homeIntent, 0);
// Setup notification
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setSmallIcon(R.drawable.ic_stat_mention);
builder.setTicker(notificationTitle);
builder.setContentTitle(notificationTitle);
builder.setContentText(notificationContent);
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL);
builder.setContentIntent(clickIntent);
builder.setNumber(statusesCount);
builder.setWhen(when);
builder.setStyle(style);
builder.setColor(pref.getNotificationLightColor());
nm.notify("mentions_" + accountId, NOTIFICATION_ID_MENTIONS_TIMELINE,
builder.build());
} finally {
statusCursor.close();
userCursor.close();
}
}
private void preloadImages(final ContentValues... values) {
if (values == null) return;
for (final ContentValues v : values) {
@ -1276,77 +1016,6 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
}
}
private int removeUnreadItems(final int tab_position, final long account_id, final long... ids) {
if (tab_position < 0 || account_id == 0 || ids == null || ids.length == 0) return 0;
final UnreadItem[] items = new UnreadItem[ids.length];
for (int i = 0, j = ids.length; i < j; i++) {
items[i] = new UnreadItem(ids[i], account_id);
}
return removeUnreadItems(tab_position, items);
}
private synchronized int removeUnreadItems(final int tab_position, final UnreadItem... items) {
if (tab_position < 0 || items == null || items.length == 0) return 0;
final int result;
final String type = CustomTabUtils.getAddedTabTypeAt(getContext(), tab_position);
if (TAB_TYPE_HOME_TIMELINE.equals(type)) {
final int size = mUnreadStatuses.size();
mUnreadStatuses.removeAll(Arrays.asList(items));
result = size - mUnreadStatuses.size();
if (result != 0) {
saveUnreadItemsFile(mUnreadStatuses, UNREAD_STATUSES_FILE_NAME);
}
} else if (TAB_TYPE_MENTIONS_TIMELINE.equals(type)) {
final int size = mUnreadMentions.size();
mUnreadMentions.removeAll(Arrays.asList(items));
result = size - mUnreadMentions.size();
if (result != 0) {
saveUnreadItemsFile(mUnreadMentions, UNREAD_MENTIONS_FILE_NAME);
}
} else if (TAB_TYPE_DIRECT_MESSAGES.equals(type)) {
final int size = mUnreadMessages.size();
mUnreadMessages.removeAll(Arrays.asList(items));
result = size - mUnreadMessages.size();
if (result != 0) {
saveUnreadItemsFile(mUnreadMessages, UNREAD_MESSAGES_FILE_NAME);
}
} else
return 0;
if (result != 0) {
notifyUnreadCountChanged(tab_position);
}
return result;
}
private void restoreUnreadItems() {
restoreUnreadItemsFile(mUnreadStatuses, UNREAD_STATUSES_FILE_NAME);
restoreUnreadItemsFile(mUnreadMentions, UNREAD_MENTIONS_FILE_NAME);
restoreUnreadItemsFile(mUnreadMessages, UNREAD_MESSAGES_FILE_NAME);
}
private void restoreUnreadItemsFile(final Collection<UnreadItem> items, final String name) {
if (items == null || name == null) return;
try {
final File file = JSONFileIO.getSerializationFile(getContext(), name);
final List<UnreadItem> restored = JSONFileIO.readArrayList(file);
if (restored != null) {
items.addAll(restored);
}
} catch (final IOException e) {
e.printStackTrace();
}
}
private void saveUnreadItemsFile(final Collection<UnreadItem> items, final String name) {
if (items == null || name == null) return;
try {
final File file = JSONFileIO.getSerializationFile(getContext(), name);
JSONFileIO.writeArray(file, items.toArray(new UnreadItem[items.size()]));
} catch (final IOException e) {
e.printStackTrace();
}
}
private void setNotificationUri(final Cursor c, final Uri uri) {
final ContentResolver cr = getContentResolver();
if (cr == null || c == null || uri == null) return;
@ -1355,30 +1024,6 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
private void updatePreferences() {
mNameFirst = mPreferences.getBoolean(KEY_NAME_FIRST, false);
mNickOnly = mPreferences.getBoolean(KEY_NICKNAME_ONLY, false);
}
private static int clearUnreadCount(final List<UnreadItem> set, final long[] accountIds) {
if (accountIds == null) return 0;
int count = 0;
for (final UnreadItem item : set.toArray(new UnreadItem[set.size()])) {
if (item != null && ArrayUtils.contains(accountIds, item.account_id) && set.remove(item)) {
count++;
}
}
return count;
}
private static List<ParcelableDirectMessage> getMessagesForAccounts(final List<ParcelableDirectMessage> items,
final long accountId) {
if (items == null) return Collections.emptyList();
final List<ParcelableDirectMessage> result = new ArrayList<>();
for (final ParcelableDirectMessage item : items.toArray(new ParcelableDirectMessage[items.size()])) {
if (item.account_id == accountId) {
result.add(item);
}
}
return result;
}
private static Cursor getPreferencesCursor(final SharedPreferencesWrapper preferences, final String key) {
@ -1413,17 +1058,6 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
return Preferences.TYPE_INVALID;
}
private static List<ParcelableStatus> getStatusesForAccounts(final List<ParcelableStatus> items,
final long accountId) {
if (items == null) return Collections.emptyList();
final List<ParcelableStatus> result = new ArrayList<>();
for (final ParcelableStatus item : items.toArray(new ParcelableStatus[items.size()])) {
if (item.account_id == accountId) {
result.add(item);
}
}
return result;
}
private static int getUnreadCount(final List<UnreadItem> set, final long... accountIds) {
if (set == null || set.isEmpty()) return 0;

View File

@ -63,6 +63,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.CachedHashtags;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.BitmapUtils;
import org.mariotaku.twidere.util.ContentValuesCreator;
import org.mariotaku.twidere.util.ListUtils;
import org.mariotaku.twidere.util.MediaUploaderInterface;
@ -403,7 +404,7 @@ public class BackgroundOperationService extends IntentService implements Constan
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, o);
final File file = new File(path);
Utils.downscaleImageIfNeeded(file, 100);
BitmapUtils.downscaleImageIfNeeded(file, 100);
final ContentLengthInputStream is = new ContentLengthInputStream(file);
is.setReadListener(new MessageMediaUploadListener(this, mNotificationManager, builder, text));
final MediaUploadResponse uploadResp = twitter.uploadMedia(file.getName(), is, o.outMimeType);
@ -507,7 +508,7 @@ public class BackgroundOperationService extends IntentService implements Constan
final String path = getImagePathFromUri(this, Uri.parse(media.uri));
final File file = path != null ? new File(path) : null;
if (!mUseUploader && file != null && file.exists()) {
Utils.downscaleImageIfNeeded(file, 95);
BitmapUtils.downscaleImageIfNeeded(file, 95);
}
}
}

View File

@ -98,7 +98,6 @@ import static org.mariotaku.twidere.provider.TwidereDataStore.STATUSES_URIS;
import static org.mariotaku.twidere.util.ContentValuesCreator.createDirectMessage;
import static org.mariotaku.twidere.util.ContentValuesCreator.createStatus;
import static org.mariotaku.twidere.util.ContentValuesCreator.createTrends;
import static org.mariotaku.twidere.util.Utils.appendQueryParameters;
import static org.mariotaku.twidere.util.Utils.getActivatedAccountIds;
import static org.mariotaku.twidere.util.Utils.getDefaultAccountId;
import static org.mariotaku.twidere.util.Utils.getNewestMessageIdsFromDatabase;
@ -1814,12 +1813,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
// Delete all rows conflicting before new data inserted.
final Expression deleteWhere = Expression.and(Expression.equals(DirectMessages.ACCOUNT_ID, accountId),
Expression.in(new Column(DirectMessages.MESSAGE_ID), new RawItemArray(messageIds)));
final Uri deleteUri = appendQueryParameters(uri, new NameValuePairImpl(QUERY_PARAM_NOTIFY,
false));
final Uri deleteUri = UriUtils.appendQueryParameters(uri, QUERY_PARAM_NOTIFY, false);
mResolver.delete(deleteUri, deleteWhere.getSQL(), null);
// Insert previously fetched items.
final Uri insertUri = appendQueryParameters(uri, new NameValuePairImpl(QUERY_PARAM_NOTIFY, notify));
final Uri insertUri = UriUtils.appendQueryParameters(uri, QUERY_PARAM_NOTIFY, notify);
bulkInsert(mResolver, insertUri, valuesArray);
return false;
}
@ -2062,7 +2060,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
final Expression accountWhere = Expression.equals(Statuses.ACCOUNT_ID, accountId);
final Expression statusWhere = Expression.in(new Column(Statuses.STATUS_ID), new RawItemArray(statusIds));
final String deleteWhere = Expression.and(accountWhere, statusWhere).getSQL();
final Uri deleteUri = appendQueryParameters(uri, new NameValuePairImpl(QUERY_PARAM_NOTIFY, false));
final Uri deleteUri = UriUtils.appendQueryParameters(uri, QUERY_PARAM_NOTIFY, false);
final int rowsDeleted = mResolver.delete(deleteUri, deleteWhere, null);
// UCD
ProfilingUtil.profile(mContext, accountId,
@ -2071,7 +2069,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
SpiceProfilingUtil.profile(mContext, accountId, accountId + ",Refresh," + TwidereArrayUtils.toString(statusIds, ',', true));
//end
// Insert previously fetched items.
final Uri insertUri = appendQueryParameters(uri, new NameValuePairImpl(QUERY_PARAM_NOTIFY, notify));
final Uri insertUri = UriUtils.appendQueryParameters(uri, QUERY_PARAM_NOTIFY, notify);
bulkInsert(mResolver, insertUri, values);
// Insert a gap.
@ -2085,7 +2083,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
gapValue.put(Statuses.IS_GAP, 1);
final Expression where = Expression.and(Expression.equals(Statuses.ACCOUNT_ID, accountId),
Expression.equals(Statuses.STATUS_ID, minId));
final Uri updateUri = appendQueryParameters(uri, new NameValuePairImpl(QUERY_PARAM_NOTIFY, true));
final Uri updateUri = UriUtils.appendQueryParameters(uri, QUERY_PARAM_NOTIFY, true);
mResolver.update(updateUri, gapValue, where.getSQL(), null);
}
return false;

View File

@ -17,58 +17,130 @@
package org.mariotaku.twidere.util;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import org.mariotaku.twidere.util.MathUtils;
import org.mariotaku.twidere.TwidereConstants;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class BitmapUtils {
// Find the max x that 1 / x <= scale.
public static int computeSampleSize(final float scale) {
if (scale <= 0) return 1;
final int initialSize = Math.max(1, (int) Math.ceil(1 / scale));
return initialSize <= 8 ? MathUtils.nextPowerOf2(initialSize) : (initialSize + 7) / 8 * 8;
}
// Find the max x that 1 / x <= scale.
public static int computeSampleSize(final float scale) {
if (scale <= 0) return 1;
final int initialSize = Math.max(1, (int) Math.ceil(1 / scale));
return initialSize <= 8 ? MathUtils.nextPowerOf2(initialSize) : (initialSize + 7) / 8 * 8;
}
// This computes a sample size which makes the longer side at least
// minSideLength long. If that's not possible, return 1.
public static int computeSampleSizeLarger(final int w, final int h, final int minSideLength) {
final int initialSize = Math.max(w / minSideLength, h / minSideLength);
if (initialSize <= 1) return 1;
// This computes a sample size which makes the longer side at least
// minSideLength long. If that's not possible, return 1.
public static int computeSampleSizeLarger(final int w, final int h, final int minSideLength) {
final int initialSize = Math.max(w / minSideLength, h / minSideLength);
if (initialSize <= 1) return 1;
return initialSize <= 8 ? MathUtils.prevPowerOf2(initialSize) : initialSize / 8 * 8;
}
return initialSize <= 8 ? MathUtils.prevPowerOf2(initialSize) : initialSize / 8 * 8;
}
// Resize the bitmap if each side is >= targetSize * 2
public static Bitmap resizeDownIfTooBig(final Bitmap bitmap, final int targetSize, final boolean recycle) {
final int srcWidth = bitmap.getWidth();
final int srcHeight = bitmap.getHeight();
final float scale = Math.max((float) targetSize / srcWidth, (float) targetSize / srcHeight);
if (scale > 0.5f) return bitmap;
return resizeBitmapByScale(bitmap, scale, recycle);
}
public static boolean downscaleImageIfNeeded(final File imageFile, final int quality) {
if (imageFile == null || !imageFile.isFile()) return false;
final String path = imageFile.getAbsolutePath();
final BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, o);
// Corrupted image, so return now.
if (o.outWidth <= 0 || o.outHeight <= 0) return false;
o.inJustDecodeBounds = false;
if (o.outWidth > TwidereConstants.TWITTER_MAX_IMAGE_WIDTH || o.outHeight > TwidereConstants.TWITTER_MAX_IMAGE_HEIGHT) {
// The image dimension is larger than Twitter's limit.
o.inSampleSize = Utils.calculateInSampleSize(o.outWidth, o.outHeight, TwidereConstants.TWITTER_MAX_IMAGE_WIDTH,
TwidereConstants.TWITTER_MAX_IMAGE_HEIGHT);
try {
final Bitmap b = BitmapDecodeHelper.decode(path, o);
final Bitmap.CompressFormat format = Utils.getBitmapCompressFormatByMimetype(o.outMimeType,
Bitmap.CompressFormat.PNG);
final FileOutputStream fos = new FileOutputStream(imageFile);
return b.compress(format, quality, fos);
} catch (final OutOfMemoryError e) {
return false;
} catch (final FileNotFoundException e) {
// This shouldn't happen.
} catch (final IllegalArgumentException e) {
return false;
}
} else if (imageFile.length() > TwidereConstants.TWITTER_MAX_IMAGE_SIZE) {
// The file size is larger than Twitter's limit.
try {
final Bitmap b = BitmapDecodeHelper.decode(path, o);
final FileOutputStream fos = new FileOutputStream(imageFile);
return b.compress(Bitmap.CompressFormat.JPEG, 80, fos);
} catch (final OutOfMemoryError e) {
return false;
} catch (final FileNotFoundException e) {
// This shouldn't happen.
}
}
return true;
}
private static Bitmap.Config getConfig(final Bitmap bitmap) {
Bitmap.Config config = bitmap.getConfig();
if (config == null) {
config = Bitmap.Config.RGB_565;
}
return config;
}
public static Bitmap getCircleBitmap(Bitmap bitmap) {
final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(output);
private static Bitmap resizeBitmapByScale(final Bitmap bitmap, final float scale, final boolean recycle) {
final int width = Math.round(bitmap.getWidth() * scale);
final int height = Math.round(bitmap.getHeight() * scale);
if (width == bitmap.getWidth() && height == bitmap.getHeight()) return bitmap;
final Bitmap target = Bitmap.createBitmap(width, height, getConfig(bitmap));
final Canvas canvas = new Canvas(target);
canvas.scale(scale, scale);
final Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
canvas.drawBitmap(bitmap, 0, 0, paint);
if (recycle) {
bitmap.recycle();
}
return target;
}
final int color = Color.RED;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawOval(rectF, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
// Resize the bitmap if each side is >= targetSize * 2
public static Bitmap resizeDownIfTooBig(final Bitmap bitmap, final int targetSize, final boolean recycle) {
final int srcWidth = bitmap.getWidth();
final int srcHeight = bitmap.getHeight();
final float scale = Math.max((float) targetSize / srcWidth, (float) targetSize / srcHeight);
if (scale > 0.5f) return bitmap;
return resizeBitmapByScale(bitmap, scale, recycle);
}
private static Bitmap.Config getConfig(final Bitmap bitmap) {
Bitmap.Config config = bitmap.getConfig();
if (config == null) {
config = Bitmap.Config.RGB_565;
}
return config;
}
private static Bitmap resizeBitmapByScale(final Bitmap bitmap, final float scale, final boolean recycle) {
final int width = Math.round(bitmap.getWidth() * scale);
final int height = Math.round(bitmap.getHeight() * scale);
if (width == bitmap.getWidth() && height == bitmap.getHeight()) return bitmap;
final Bitmap target = Bitmap.createBitmap(width, height, getConfig(bitmap));
final Canvas canvas = new Canvas(target);
canvas.scale(scale, scale);
final Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG);
canvas.drawBitmap(bitmap, 0, 0, paint);
if (recycle) {
bitmap.recycle();
}
return target;
}
}

View File

@ -35,35 +35,45 @@ public class ContentListScrollListener extends OnScrollListener {
private int mScrollSum;
private int mTouchSlop;
private ContentListAware mContentListAware;
private ContentListSupport mContentListSupport;
private OnScrollListener mOnScrollListener;
public ContentListScrollListener(@NonNull ContentListAware contentListAware) {
mContentListAware = contentListAware;
public ContentListScrollListener(@NonNull ContentListSupport contentListSupport) {
mContentListSupport = contentListSupport;
}
public void setOnScrollListener(OnScrollListener listener) {
mOnScrollListener = listener;
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (mOnScrollListener != null) {
mOnScrollListener.onScrollStateChanged(recyclerView, newState);
}
mScrollState = newState;
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (mOnScrollListener != null) {
mOnScrollListener.onScrolled(recyclerView, dx, dy);
}
//Reset mScrollSum when scrolling in reverse direction
if (dy * mScrollSum < 0) {
mScrollSum = 0;
}
mScrollSum += dy;
if (Math.abs(mScrollSum) > mTouchSlop) {
mContentListAware.setControlVisible(dy < 0);
mContentListSupport.setControlVisible(dy < 0);
mScrollSum = 0;
}
final IContentCardAdapter adapter = mContentListAware.getAdapter();
final IContentCardAdapter adapter = mContentListSupport.getAdapter();
final LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
if (!mContentListAware.isRefreshing() && adapter.hasLoadMoreIndicator() && mScrollState != RecyclerView.SCROLL_STATE_IDLE
if (!mContentListSupport.isRefreshing() && adapter.hasLoadMoreIndicator() && mScrollState != RecyclerView.SCROLL_STATE_IDLE
&& layoutManager.findLastVisibleItemPosition() == adapter.getItemCount() - 1) {
mContentListAware.onLoadMoreContents();
mContentListSupport.onLoadMoreContents();
}
}
@ -72,7 +82,7 @@ public class ContentListScrollListener extends OnScrollListener {
mTouchSlop = touchSlop;
}
public static interface ContentListAware {
public static interface ContentListSupport {
boolean isRefreshing();

View File

@ -1,43 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util;
import org.apache.http.NameValuePair;
public class NameValuePairImpl implements NameValuePair {
private final String name, value;
public NameValuePairImpl(final String name, final Object value) {
this.name = name;
this.value = ParseUtils.parseString(value);
}
@Override
public String getName() {
return name;
}
@Override
public String getValue() {
return value;
}
}

View File

@ -27,24 +27,29 @@ import org.mariotaku.twidere.Constants;
public class PositionManager implements Constants {
private final SharedPreferencesWrapper mPreferences;
private final SharedPreferencesWrapper mPreferences;
public PositionManager(final Context context) {
public PositionManager(final Context context) {
mPreferences = SharedPreferencesWrapper.getInstance(context,
TIMELINE_POSITIONS_PREFERENCES_NAME, Context.MODE_PRIVATE);
}
}
public long getPosition(final String key) {
if (TextUtils.isEmpty(key)) return -1;
return mPreferences.getLong(key, -1);
}
public long getPosition(final String key) {
if (TextUtils.isEmpty(key)) return -1;
return mPreferences.getLong(key, -1);
}
public boolean setPosition(final String key, final long status_id) {
if (TextUtils.isEmpty(key)) return false;
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putLong(key, status_id);
editor.apply();
return true;
}
public boolean setPosition(final String key, final long id) {
return setPosition(key, id, false);
}
public boolean setPosition(final String key, final long id, boolean acceptOlder) {
if (TextUtils.isEmpty(key) || !acceptOlder && getPosition(key) > id) return false;
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putLong(key, id);
editor.apply();
return true;
}
}

View File

@ -0,0 +1,42 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util;
import android.net.Uri;
/**
* Created by mariotaku on 15/3/23.
*/
public class UriUtils {
public static Uri appendQueryParameters(final Uri uri, final String key, long value) {
return appendQueryParameters(uri, key, ParseUtils.parseString(value));
}
public static Uri appendQueryParameters(final Uri uri, final String key, String value) {
final Uri.Builder builder = uri.buildUpon();
builder.appendQueryParameter(key, value);
return builder.build();
}
public static Uri appendQueryParameters(Uri uri, String key, boolean value) {
return appendQueryParameters(uri, key, ParseUtils.parseString(value));
}
}

View File

@ -25,7 +25,6 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.graphics.Color;
import android.support.v4.util.LongSparseArray;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.TwidereConstants;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableUser;
@ -43,22 +42,22 @@ public class UserColorNameUtils implements TwidereConstants {
throw new AssertionError();
}
public static void clearUserColor(final Context context, final long user_id) {
public static void clearUserColor(final Context context, final long userId) {
if (context == null) return;
sUserColors.remove(user_id);
sUserColors.remove(userId);
final SharedPreferences prefs = context.getSharedPreferences(USER_COLOR_PREFERENCES_NAME, Context.MODE_PRIVATE);
final SharedPreferences.Editor editor = prefs.edit();
editor.remove(Long.toString(user_id));
editor.remove(Long.toString(userId));
editor.apply();
}
public static void clearUserNickname(final Context context, final long user_id) {
public static void clearUserNickname(final Context context, final long userId) {
if (context == null) return;
sUserNicknames.remove(user_id);
sUserNicknames.remove(userId);
final SharedPreferences prefs = context.getSharedPreferences(USER_NICKNAME_PREFERENCES_NAME,
Context.MODE_PRIVATE);
final SharedPreferences.Editor editor = prefs.edit();
editor.remove(Long.toString(user_id));
editor.remove(Long.toString(userId));
editor.apply();
}
@ -80,41 +79,30 @@ public class UserColorNameUtils implements TwidereConstants {
if (context == null) return null;
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
final boolean nameFirst = prefs.getBoolean(KEY_NAME_FIRST, true);
final boolean nicknameOnly = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
.getBoolean(KEY_NICKNAME_ONLY, false);
return getDisplayName(context, userId, name, screenName, nameFirst, nicknameOnly, ignoreCache);
}
public static String getDisplayName(final Context context, final long user_id, final String name,
final String screen_name, final boolean name_first, final boolean nickname_only) {
return getDisplayName(context, user_id, name, screen_name, name_first, nickname_only, false);
return getDisplayName(context, userId, name, screenName, nameFirst, ignoreCache);
}
public static String getDisplayName(final Context context, final ParcelableUser user,
final boolean nameFirst, final boolean nicknameOnly,
final boolean ignoreCache) {
return getDisplayName(context, user.id, user.name, user.screen_name,
nameFirst, nicknameOnly, ignoreCache);
final boolean nameFirst, final boolean ignoreCache) {
return getDisplayName(context, user.id, user.name, user.screen_name, nameFirst, ignoreCache);
}
public static String getDisplayName(final Context context, final ParcelableStatus status,
final boolean nameFirst, final boolean nicknameOnly,
final boolean nameFirst,
final boolean ignoreCache) {
return getDisplayName(context, status.user_id, status.user_name, status.user_screen_name,
nameFirst, nicknameOnly, ignoreCache);
nameFirst, ignoreCache);
}
public static String getDisplayName(final Context context, final long userId, final String name,
final String screenName, final boolean nameFirst,
final boolean nicknameOnly, final boolean ignoreCache) {
final boolean ignoreCache) {
if (context == null) return null;
final String nick = getUserNickname(context, userId, ignoreCache);
final boolean nick_available = !isEmpty(nick);
if (nicknameOnly && nick_available) return nick;
if (!nick_available) return nameFirst && !isEmpty(name) ? name : "@" + screenName;
return context.getString(R.string.name_with_nickname, nameFirst && !isEmpty(name) ? name : "@" + screenName,
nick);
final boolean nickAvailable = !isEmpty(nick);
if (nickAvailable) return nick;
return nameFirst && !isEmpty(name) ? name : "@" + screenName;
}
public static int getUserColor(final Context context, final long user_id) {
@ -145,12 +133,13 @@ public class UserColorNameUtils implements TwidereConstants {
return nickname;
}
public static String getUserNickname(final Context context, final long user_id, final String name) {
final String nick = getUserNickname(context, user_id);
if (isEmpty(nick)) return name;
final boolean nickname_only = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
.getBoolean(KEY_NICKNAME_ONLY, false);
return nickname_only ? nick : context.getString(R.string.name_with_nickname, name, nick);
public static String getUserNickname(final Context context, final long userId, final String name) {
return getUserNickname(context, userId, name, false);
}
public static String getUserNickname(final Context context, final long userId, final String name, final boolean ignoreCache) {
final String nick = getUserNickname(context, userId, ignoreCache);
return isEmpty(nick) ? name : nick;
}
public static void initUserColor(final Context context) {

View File

@ -42,15 +42,9 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
@ -115,7 +109,6 @@ import android.widget.TextView;
import android.widget.Toast;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.http.NameValuePair;
import org.json.JSONException;
import org.mariotaku.jsonserializer.JSONSerializer;
import org.mariotaku.querybuilder.AllColumns;
@ -212,8 +205,6 @@ import org.mariotaku.twidere.view.ShapedImageView.ShapeStyle;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -546,16 +537,6 @@ public final class Utils implements Constants, TwitterConstants {
accessibilityManager.sendAccessibilityEvent(event);
}
public static Uri appendQueryParameters(final Uri uri, final NameValuePair... params) {
final Uri.Builder builder = uri.buildUpon();
if (params != null) {
for (final NameValuePair param : params) {
builder.appendQueryParameter(param.getName(), param.getValue());
}
}
return builder.build();
}
public static String buildActivatedStatsWhereClause(final Context context, final String selection) {
if (context == null) return null;
final long[] account_ids = getActivatedAccountIds(context);
@ -728,7 +709,6 @@ public final class Utils implements Constants, TwitterConstants {
adapter.setDisplayProfileImage(pref.getBoolean(KEY_DISPLAY_PROFILE_IMAGE, true));
adapter.setDisplayNameFirst(pref.getBoolean(KEY_NAME_FIRST, true));
adapter.setLinkHighlightOption(pref.getString(KEY_LINK_HIGHLIGHT_OPTION, VALUE_LINK_HIGHLIGHT_OPTION_NONE));
adapter.setNicknameOnly(pref.getBoolean(KEY_NICKNAME_ONLY, false));
adapter.setTextSize(pref.getInt(KEY_TEXT_SIZE, getDefaultTextSize(context)));
adapter.notifyDataSetChanged();
}
@ -758,27 +738,6 @@ public final class Utils implements Constants, TwitterConstants {
return colors;
}
public static Bitmap getCircleBitmap(Bitmap bitmap) {
final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(),
Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(output);
final int color = Color.RED;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
final RectF rectF = new RectF(rect);
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
canvas.drawOval(rectF, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
public static Fragment createFragmentForIntent(final Context context, final Intent intent) {
final Uri uri = intent.getData();
@ -1137,47 +1096,6 @@ public final class Utils implements Constants, TwitterConstants {
return intent;
}
public static boolean downscaleImageIfNeeded(final File imageFile, final int quality) {
if (imageFile == null || !imageFile.isFile()) return false;
final String path = imageFile.getAbsolutePath();
final BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, o);
// Corrupted image, so return now.
if (o.outWidth <= 0 || o.outHeight <= 0) return false;
o.inJustDecodeBounds = false;
if (o.outWidth > TWITTER_MAX_IMAGE_WIDTH || o.outHeight > TWITTER_MAX_IMAGE_HEIGHT) {
// The image dimension is larger than Twitter's limit.
o.inSampleSize = calculateInSampleSize(o.outWidth, o.outHeight, TWITTER_MAX_IMAGE_WIDTH,
TWITTER_MAX_IMAGE_HEIGHT);
try {
final Bitmap b = BitmapDecodeHelper.decode(path, o);
final Bitmap.CompressFormat format = getBitmapCompressFormatByMimetype(o.outMimeType,
Bitmap.CompressFormat.PNG);
final FileOutputStream fos = new FileOutputStream(imageFile);
return b.compress(format, quality, fos);
} catch (final OutOfMemoryError e) {
return false;
} catch (final FileNotFoundException e) {
// This shouldn't happen.
} catch (final IllegalArgumentException e) {
return false;
}
} else if (imageFile.length() > TWITTER_MAX_IMAGE_SIZE) {
// The file size is larger than Twitter's limit.
try {
final Bitmap b = BitmapDecodeHelper.decode(path, o);
final FileOutputStream fos = new FileOutputStream(imageFile);
return b.compress(Bitmap.CompressFormat.JPEG, 80, fos);
} catch (final OutOfMemoryError e) {
return false;
} catch (final FileNotFoundException e) {
// This shouldn't happen.
}
}
return true;
}
public static String encodeQueryParams(final String value) throws IOException {
final String encoded = URLEncoder.encode(value, "UTF-8");
final StringBuilder buf = new StringBuilder();
@ -2213,13 +2131,6 @@ public final class Utils implements Constants, TwitterConstants {
return 0;
}
public static String getSampleDisplayName(final Context context, final boolean name_first,
final boolean nickname_only) {
if (context == null) return null;
if (nickname_only) return TWIDERE_PREVIEW_NICKNAME;
return context.getString(R.string.name_with_nickname, name_first ? TWIDERE_PREVIEW_NAME : "@"
+ TWIDERE_PREVIEW_SCREEN_NAME, TWIDERE_PREVIEW_NICKNAME);
}
public static String getSenderUserName(final Context context, final ParcelableDirectMessage user) {
if (context == null || user == null) return null;
@ -3507,38 +3418,6 @@ public final class Utils implements Constants, TwitterConstants {
return text.replaceFirst("(?s)" + regex + "(?!.*?" + regex + ")", replacement);
}
/**
* Resizes specific a Bitmap with keeping ratio.
*/
public static Bitmap resizeBitmap(Bitmap orig, final int desireWidth, final int desireHeight) {
final int width = orig.getWidth();
final int height = orig.getHeight();
if (0 < width && 0 < height && desireWidth < width || desireHeight < height) {
// Calculate scale
float scale;
if (width < height) {
scale = (float) desireHeight / (float) height;
if (desireWidth < width * scale) {
scale = (float) desireWidth / (float) width;
}
} else {
scale = (float) desireWidth / (float) width;
}
// Draw resized image
final Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
final Bitmap bitmap = Bitmap.createBitmap(orig, 0, 0, width, height, matrix, true);
final Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(bitmap, 0, 0, null);
orig = bitmap;
}
return orig;
}
public static void restartActivity(final Activity activity) {
if (activity == null) return;
final int enter_anim = android.R.anim.fade_in;

View File

@ -45,7 +45,11 @@ public class StatusComposeEditText extends ThemedMultiAutoCompleteTextView imple
public StatusComposeEditText(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
mAdapter = new UserHashtagAutoCompleteAdapter(this);
if (isInEditMode()) {
mAdapter = null;
} else {
mAdapter = new UserHashtagAutoCompleteAdapter(this);
}
setTokenizer(new ScreenNameTokenizer());
setMovementMethod(ArrowKeyMovementMethod.getInstance());
setRawInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES

View File

@ -11,7 +11,7 @@ import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.FixedLinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.SparseIntArray;
@ -359,7 +359,7 @@ public class TabPagerIndicator extends RecyclerView implements PagerIndicator {
}
}
private static class TabLayoutManager extends LinearLayoutManager {
private static class TabLayoutManager extends FixedLinearLayoutManager {
private final TabPagerIndicator mIndicator;

View File

@ -23,7 +23,6 @@ import android.content.Context;
import android.database.Cursor;
import android.graphics.Color;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
@ -76,9 +75,7 @@ public class MessageEntryViewHolder extends ViewHolder implements OnClickListene
final String name = cursor.getString(ConversationEntries.IDX_NAME);
final String screenName = cursor.getString(ConversationEntries.IDX_SCREEN_NAME);
final String nick = getUserNickname(context, conversationId);
nameView.setText(TextUtils.isEmpty(nick) ? name : adapter.isNicknameOnly() ? nick : context.getString(
R.string.name_with_nickname, name, nick));
nameView.setText(getUserNickname(context, conversationId, name));
screenNameView.setText("@" + screenName);
textView.setText(toPlainText(cursor.getString(ConversationEntries.IDX_TEXT)));
timeView.setTime(timestamp);

View File

@ -21,8 +21,8 @@ import org.mariotaku.twidere.model.ParcelableMedia;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.ParcelableStatus.CursorIndices;
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.ImageLoadingHandler;
import org.mariotaku.twidere.util.MediaLoaderWrapper;
import org.mariotaku.twidere.util.SimpleValueSerializer;
import org.mariotaku.twidere.util.TwitterCardUtils;
import org.mariotaku.twidere.util.UserColorNameUtils;
@ -103,9 +103,8 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
displayStatus(adapter.getContext(), adapter.getImageLoader(),
adapter.getImageLoadingHandler(), adapter.getTwitterWrapper(),
adapter.isMediaPreviewEnabled(), adapter.shouldShowAccountsColor(),
displayInReplyTo, adapter.isNameFirst(), adapter.isNicknameOnly(),
adapter.getProfileImageStyle(), adapter.getMediaPreviewStyle(),
status, null, displayInReplyTo);
displayInReplyTo, adapter.isNameFirst(), adapter.getProfileImageStyle(),
adapter.getMediaPreviewStyle(), status, null, displayInReplyTo);
}
public void displayStatus(@NonNull final Context context,
@ -113,7 +112,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
@NonNull final ImageLoadingHandler handler,
@NonNull final AsyncTwitterWrapper twitter,
final boolean displayMediaPreview, final boolean displayAccountsColor,
final boolean displayInReplyTo, boolean nameFirst, boolean nicknameOnly,
final boolean displayInReplyTo, boolean nameFirst,
final int profileImageStyle, final int mediaPreviewStyle,
@NonNull final ParcelableStatus status,
@Nullable final TranslationResult translation, boolean shouldDisplayExtraType) {
@ -124,14 +123,14 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
replyRetweetView.setVisibility(View.VISIBLE);
replyRetweetIcon.setVisibility(View.VISIBLE);
final String retweetedBy = UserColorNameUtils.getDisplayName(context, status.retweeted_by_id,
status.retweeted_by_name, status.retweeted_by_screen_name, nameFirst, nicknameOnly);
status.retweeted_by_name, status.retweeted_by_screen_name, nameFirst);
replyRetweetView.setText(context.getString(R.string.name_retweeted, retweetedBy));
replyRetweetIcon.setImageResource(R.drawable.ic_activity_action_retweet);
} else if (status.in_reply_to_status_id > 0 && status.in_reply_to_user_id > 0 && displayInReplyTo) {
replyRetweetView.setVisibility(View.VISIBLE);
replyRetweetIcon.setVisibility(View.VISIBLE);
final String inReplyTo = UserColorNameUtils.getDisplayName(context, status.in_reply_to_user_id,
status.in_reply_to_name, status.in_reply_to_screen_name, nameFirst, nicknameOnly);
status.in_reply_to_name, status.in_reply_to_screen_name, nameFirst);
replyRetweetView.setText(context.getString(R.string.in_reply_to_name, inReplyTo));
replyRetweetIcon.setImageResource(R.drawable.ic_activity_action_reply);
} else {
@ -232,7 +231,6 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
final AsyncTwitterWrapper twitter = adapter.getTwitterWrapper();
final Context context = adapter.getContext();
final boolean nameFirst = adapter.isNameFirst();
final boolean nicknameOnly = adapter.isNicknameOnly();
final long reply_count = cursor.getLong(indices.reply_count);
final long retweet_count;
@ -266,14 +264,14 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
if (retweet_id > 0) {
final String retweetedBy = UserColorNameUtils.getDisplayName(context, retweeted_by_id,
retweeted_by_name, retweeted_by_screen_name, nameFirst, nicknameOnly);
retweeted_by_name, retweeted_by_screen_name, nameFirst);
replyRetweetView.setText(context.getString(R.string.name_retweeted, retweetedBy));
replyRetweetIcon.setImageResource(R.drawable.ic_activity_action_retweet);
replyRetweetView.setVisibility(View.VISIBLE);
replyRetweetIcon.setVisibility(View.VISIBLE);
} else if (in_reply_to_status_id > 0 && in_reply_to_user_id > 0 && displayInReplyTo) {
final String inReplyTo = UserColorNameUtils.getDisplayName(context, in_reply_to_user_id,
in_reply_to_name, in_reply_to_screen_name, nameFirst, nicknameOnly);
in_reply_to_name, in_reply_to_screen_name, nameFirst);
replyRetweetView.setText(context.getString(R.string.in_reply_to_name, inReplyTo));
replyRetweetIcon.setImageResource(R.drawable.ic_activity_action_reply);
replyRetweetView.setVisibility(View.VISIBLE);
@ -375,7 +373,7 @@ public class StatusViewHolder extends RecyclerView.ViewHolder implements Constan
@Override
public void onClick(View v) {
if (statusClickListener == null) return;
final int position = getPosition();
final int position = getAdapterPosition();
switch (v.getId()) {
case R.id.item_content: {
statusClickListener.onStatusClick(this, position);

View File

@ -1,89 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Twidere - Twitter client for Android
~
~ Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
~
~ This program 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.
~
~ This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
-->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/checkbox"
android:layout_alignParentTop="true">
<TextView
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:text="@string/data_profiling_summary"
android:textAppearance="?android:attr/textAppearanceMedium"/>
</ScrollView>
<CheckBox
android:id="@+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/divider"
android:layout_margin="8dp"
android:checked="true"
android:text="@string/enable_data_profiling"/>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="0.2dp"
android:layout_above="@+id/buttons"
android:background="#40808080"/>
<LinearLayout
android:id="@+id/buttons"
android:layout_width="match_parent"
android:layout_height="@dimen/button_bar_height"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<Button
android:id="@+id/preview"
style="?android:borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="@string/preview"/>
<View
android:layout_width="0.2dp"
android:layout_height="match_parent"
android:background="#40808080"/>
<Button
android:id="@+id/save"
style="?android:borderlessButtonStyle"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="@android:string/ok"/>
</LinearLayout>
</RelativeLayout>

View File

@ -30,7 +30,6 @@
android:orientation="horizontal"
android:paddingLeft="@dimen/element_spacing_normal"
android:paddingRight="@dimen/element_spacing_normal"
app:backgroundColor="?cardItemBackgroundColor"
app:ignorePadding="true"
tools:context=".adapter.DirectMessagesEntryAdapter">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -0,0 +1,25 @@
<!--
~ Twidere - Twitter client for Android
~
~ Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
~
~ This program 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.
~
~ This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
-->
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>

View File

@ -99,5 +99,8 @@
<dimen name="popup_width_account_selector">160dp</dimen>
<dimen name="line_width_compose_account_profile_image">2dp</dimen>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

View File

@ -46,5 +46,9 @@
<item quantity="one">@string/N_others_quantity_one</item>
<item quantity="other">@string/N_others_quantity_other</item>
</plurals>
<plurals name="from_name_and_N_others">
<item quantity="one">@string/from_name_and_name</item>
<item quantity="other">@string/from_name_and_N_others</item>
</plurals>
</resources>

View File

@ -354,12 +354,6 @@
<string name="action_accepting_follow_request">accepting follow request</string>
<string name="action_denying_follow_request">denying follow request</string>
<string name="status_is_duplicate">Your tweet is a duplicate.</string>
<string name="data_profiling_summary">Twidere took part in a research on predicting user\'s social behavior to pre-caching content started by students in UC Davis.\n\nHere are the data we wanted to collect and why:\nCollected data:\n1. User\'s twitter ID\n2. User\'s home timeline (prediction based on user\'s interest and social interaction)\n3. User\'s click on a tweet (prediction based on user\'s interest and social interaction)\n4. Coarse location (which is good predictor when user will access twitter)\n\nTwidere will upload collected data only when Wifi available and your device connected to charger, so It will not cost you extra bandwidth fee or drain your battery power.</string>
<string name="data_profiling">Usage Statistics</string>
<string name="enable_data_profiling">Enable Reporting</string>
<string name="data_profiling_notification_ticker">Statistics Opted-In</string>
<string name="data_profiling_notification_title">Usage Statistics</string>
<string name="data_profiling_notification_desc">Enable or Disable Usage Statistics</string>
<string name="silent_notifications">Silent notifications</string>
<string name="silent_notifications_summary">Disable ringtone/vibrate for notifications</string>
<string name="disable_background_service">Disable background service</string>
@ -736,5 +730,13 @@
<string name="permission_description_shorten_status">Application can shorten tweet for Twidere, so it can access your tweet to send.</string>
<string name="permission_description_upload_media">Application can upload media for Twidere, so it can access media in your tweet to send.</string>
<string name="permission_description_sync_timeline">Application can sync read position for Twidere, so it can access your read position.</string>
<string name="title_activity_usage_statistics">UsageStatisticsActivity</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
<string name="usage_statistics_notification_summary">Help us improve Twidere!</string>
<string name="from_name">From <xliff:g id="name">%1$s</xliff:g></string>
<string name="from_name_and_name">From <xliff:g id="name">%1$s</xliff:g> and <xliff:g id="name">%2$s</xliff:g></string>
<string name="from_name_and_N_others">From <xliff:g id="name">%1$s</xliff:g> and <xliff:g id="name">%2$d</xliff:g> others</string>
</resources>

View File

@ -15,12 +15,6 @@
android:key="name_first"
android:order="22"
android:title="@string/name_first"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="nickname_only"
android:order="23"
android:summary="@string/nickname_only_summary"
android:title="@string/nickname_only"/>
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="media_preview"

View File

@ -37,7 +37,7 @@
<Preference
android:fragment="org.mariotaku.twidere.fragment.SettingsDetailsFragment"
android:key="data_profiling_settings"
android:title="@string/data_profiling">
android:title="@string/usage_statistics">
<extra
android:name="resid"
android:value="@xml/preferences_usage_statistics"/>

View File

@ -22,11 +22,15 @@
<Preference android:layout="@layout/header_usage_statistics"/>
<org.mariotaku.twidere.preference.ResourceIconPreference
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="ucd_data_profiling"
android:order="11"
android:title="@string/research_ucdavis_earlybird"/>
<org.mariotaku.twidere.preference.ResourceIconPreference
<org.mariotaku.twidere.preference.AutoFixCheckBoxPreference
android:defaultValue="false"
android:key="spice_data_profiling"
android:order="12"
android:title="@string/research_tsinghua_spice"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 28 KiB