improved image crop
This commit is contained in:
parent
105046636f
commit
5b5b1e6102
|
@ -56,7 +56,7 @@ subprojects {
|
|||
TwitterText : '1.14.3',
|
||||
MediaViewerLibrary : '0.9.23',
|
||||
MultiValueSwitch : '0.9.8',
|
||||
PickNCrop : '0.9.25',
|
||||
PickNCrop : '0.9.27',
|
||||
AndroidGIFDrawable : '1.2.6',
|
||||
KPreferences : '0.9.7',
|
||||
Kovenant : '3.3.0',
|
||||
|
@ -67,6 +67,7 @@ subprojects {
|
|||
Glide : '3.7.0',
|
||||
GlideOkHttp3 : '1.4.0',
|
||||
GlideTransformations: '2.0.1',
|
||||
AndroidImageCropper : '2.4.0',
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
@ -19,10 +19,46 @@
|
|||
package org.mariotaku.microblog.library.mastodon.model;
|
||||
|
||||
import org.mariotaku.restfu.http.SimpleValueMap;
|
||||
import org.mariotaku.restfu.http.mime.Body;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/4/17.
|
||||
*/
|
||||
|
||||
public class AccountUpdate extends SimpleValueMap {
|
||||
|
||||
public AccountUpdate displayName(String displayName) {
|
||||
if (displayName != null) {
|
||||
put("display_name", displayName);
|
||||
} else {
|
||||
put("display_name", null);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public AccountUpdate note(String note) {
|
||||
if (note != null) {
|
||||
put("note", note);
|
||||
} else {
|
||||
put("note", null);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public AccountUpdate avatar(Body avatar) {
|
||||
if (avatar != null) {
|
||||
put("avatar", avatar);
|
||||
} else {
|
||||
put("avatar", null);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public AccountUpdate header(Body header) {
|
||||
if (header != null) {
|
||||
put("header", header);
|
||||
} else {
|
||||
put("header", null);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,7 +161,6 @@ dependencies {
|
|||
compile "org.apache.james:apache-mime4j-core:${libVersions['Mime4J']}"
|
||||
compile "org.apache.james:apache-mime4j-storage:${libVersions['Mime4J']}"
|
||||
compile "com.bluelinelabs:logansquare:${libVersions['LoganSquare']}"
|
||||
compile 'com.soundcloud.android:android-crop:1.0.1@aar'
|
||||
compile "com.hannesdorfmann.parcelableplease:annotation:${libVersions['ParcelablePlease']}"
|
||||
compile "com.github.mariotaku:PickNCrop:${libVersions['PickNCrop']}"
|
||||
compile "com.github.mariotaku.RestFu:library:${libVersions['RestFu']}"
|
||||
|
@ -178,6 +177,7 @@ dependencies {
|
|||
compile "com.github.bumptech.glide:glide:${libVersions['Glide']}"
|
||||
compile "com.github.bumptech.glide:okhttp3-integration:${libVersions['GlideOkHttp3']}@aar"
|
||||
compile "jp.wasabeef:glide-transformations:${libVersions['GlideTransformations']}"
|
||||
compile "com.theartofdev.edmodo:android-image-cropper:${libVersions['AndroidImageCropper']}"
|
||||
|
||||
compile "com.github.mariotaku.MediaViewerLibrary:base:${libVersions['MediaViewerLibrary']}"
|
||||
compile "com.github.mariotaku.MediaViewerLibrary:subsample-image-view:${libVersions['MediaViewerLibrary']}"
|
||||
|
|
|
@ -528,8 +528,8 @@
|
|||
android:theme="@style/Theme.Twidere"/>
|
||||
<activity
|
||||
android:name=".activity.ImageCropperActivity"
|
||||
android:label="@string/crop_image"
|
||||
android:theme="@style/Theme.Twidere.NoActionBar"
|
||||
android:label="@string/title_crop_image"
|
||||
android:theme="@style/Theme.Twidere"
|
||||
android:windowSoftInputMode="adjustResize"/>
|
||||
<activity
|
||||
android:name=".activity.IncompatibleAlertActivity"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
* Copyright (C) 2012-2017 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
|
||||
|
@ -19,55 +19,164 @@
|
|||
|
||||
package org.mariotaku.twidere.activity
|
||||
|
||||
import android.content.Context
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.support.v7.widget.Toolbar
|
||||
import com.soundcloud.android.crop.CropImageActivity
|
||||
import org.mariotaku.kpreferences.get
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.theartofdev.edmodo.cropper.CropImage
|
||||
import com.theartofdev.edmodo.cropper.CropImageOptions
|
||||
import com.theartofdev.edmodo.cropper.CropImageView
|
||||
import kotlinx.android.synthetic.main.activity_crop_image.*
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.TwidereConstants
|
||||
import org.mariotaku.twidere.TwidereConstants.SHARED_PREFERENCES_NAME
|
||||
import org.mariotaku.twidere.activity.iface.IThemedActivity
|
||||
import org.mariotaku.twidere.constant.themeBackgroundAlphaKey
|
||||
import org.mariotaku.twidere.constant.themeBackgroundOptionKey
|
||||
import org.mariotaku.twidere.constant.themeKey
|
||||
import org.mariotaku.twidere.util.theme.getCurrentThemeResource
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/6/16.
|
||||
* Built-in activity for image cropping.
|
||||
* Use [CropImage.activity] to create a builder to start this activity.
|
||||
*/
|
||||
class ImageCropperActivity : CropImageActivity(), IThemedActivity {
|
||||
class ImageCropperActivity : BaseActivity(), CropImageView.OnSetImageUriCompleteListener, CropImageView.OnCropImageCompleteListener {
|
||||
|
||||
// Data fields
|
||||
override val currentThemeBackgroundAlpha by lazy { themeBackgroundAlpha }
|
||||
override val currentThemeBackgroundOption by lazy { themeBackgroundOption }
|
||||
/**
|
||||
* Persist URI image to crop URI if specific permissions are required
|
||||
*/
|
||||
private val cropImageUri: Uri get() = intent.getParcelableExtra(CropImage.CROP_IMAGE_EXTRA_SOURCE)
|
||||
|
||||
private val preferences by lazy { getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) }
|
||||
/**
|
||||
* the options that were set for the crop image
|
||||
*/
|
||||
private val options: CropImageOptions get() = intent.getParcelableExtra(CropImage.CROP_IMAGE_EXTRA_OPTIONS)
|
||||
|
||||
private var doneCancelBar: Toolbar? = null
|
||||
/**
|
||||
* Get Android uri to save the cropped image into.<br></br>
|
||||
* Use the given in options or create a temp file.
|
||||
*/
|
||||
private val outputUri: Uri get() = options.outputUri
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
val prefs = getSharedPreferences(TwidereConstants.SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)
|
||||
val themeResource = getCurrentThemeResource(this, prefs[themeKey])
|
||||
if (themeResource != 0) {
|
||||
setTheme(themeResource)
|
||||
}
|
||||
@SuppressLint("NewApi")
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_crop_image)
|
||||
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
// no permissions required or already grunted, can start crop image activity
|
||||
cropImageView.setImageUriAsync(cropImageUri)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onContentChanged() {
|
||||
super.onContentChanged()
|
||||
doneCancelBar = findViewById(R.id.done_cancel_bar) as Toolbar
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
cropImageView.setOnSetImageUriCompleteListener(this)
|
||||
cropImageView.setOnCropImageCompleteListener(this)
|
||||
}
|
||||
|
||||
override fun setContentView(layoutResID: Int) {
|
||||
super.setContentView(R.layout.activity_image_cropper)
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
cropImageView.setOnSetImageUriCompleteListener(null)
|
||||
cropImageView.setOnCropImageCompleteListener(null)
|
||||
}
|
||||
|
||||
override val themeBackgroundAlpha: Int
|
||||
get() = preferences[themeBackgroundAlphaKey]
|
||||
override fun onBackPressed() {
|
||||
setResultCancel()
|
||||
}
|
||||
|
||||
override val themeBackgroundOption: String
|
||||
get() = preferences[themeBackgroundOptionKey]
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
setResultCancel()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
super.onCreateOptionsMenu(menu)
|
||||
menuInflater.inflate(R.menu.menu_crop_image, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.perform_crop -> {
|
||||
cropImage()
|
||||
return true
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun onSetImageUriComplete(view: CropImageView, uri: Uri, error: Exception?) {
|
||||
if (error == null) {
|
||||
if (options.initialCropWindowRectangle != null) {
|
||||
cropImageView.cropRect = options.initialCropWindowRectangle
|
||||
}
|
||||
if (options.initialRotation > -1) {
|
||||
cropImageView.rotatedDegrees = options.initialRotation
|
||||
}
|
||||
} else {
|
||||
setResult(null, error, 1)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCropImageComplete(view: CropImageView, result: CropImageView.CropResult) {
|
||||
setResult(result.uri, result.error, result.sampleSize)
|
||||
}
|
||||
|
||||
//region: Private methods
|
||||
|
||||
/**
|
||||
* Execute crop image and save the result to output uri.
|
||||
*/
|
||||
private fun cropImage() {
|
||||
if (options.noOutputImage) {
|
||||
setResult(null, null, 1)
|
||||
} else {
|
||||
val outputUri = outputUri
|
||||
cropImageView.saveCroppedImageAsync(outputUri,
|
||||
options.outputCompressFormat,
|
||||
options.outputCompressQuality,
|
||||
options.outputRequestWidth,
|
||||
options.outputRequestHeight,
|
||||
options.outputRequestSizeOptions)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the image in the crop image view.
|
||||
*/
|
||||
protected fun rotateImage(degrees: Int) {
|
||||
cropImageView.rotateImage(degrees)
|
||||
}
|
||||
|
||||
/**
|
||||
* Result with cropped image data or error if failed.
|
||||
*/
|
||||
private fun setResult(uri: Uri?, error: Exception?, sampleSize: Int) {
|
||||
val resultCode = if (error == null) Activity.RESULT_OK else CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE
|
||||
setResult(resultCode, getResultIntent(uri, error, sampleSize))
|
||||
finish()
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel of cropping activity.
|
||||
*/
|
||||
private fun setResultCancel() {
|
||||
setResult(Activity.RESULT_CANCELED)
|
||||
finish()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get intent instance to be used for the result of this activity.
|
||||
*/
|
||||
private fun getResultIntent(uri: Uri?, error: Exception?, sampleSize: Int): Intent {
|
||||
val result = CropImage.ActivityResult(cropImageView.imageUri, uri, error,
|
||||
cropImageView.cropPoints, cropImageView.cropRect, cropImageView.rotatedDegrees,
|
||||
sampleSize)
|
||||
val intent = Intent()
|
||||
intent.putExtra(CropImage.CROP_IMAGE_EXTRA_RESULT, result)
|
||||
return intent
|
||||
}
|
||||
|
||||
//endregion
|
||||
}
|
||||
|
||||
|
|
|
@ -24,34 +24,36 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.os.Parcelable
|
||||
import android.support.v4.app.DialogFragment
|
||||
import android.support.v4.app.FragmentActivity
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks
|
||||
import android.support.v4.content.Loader
|
||||
import android.text.Editable
|
||||
import android.text.TextUtils
|
||||
import android.text.TextUtils.isEmpty
|
||||
import android.text.TextWatcher
|
||||
import android.view.*
|
||||
import android.view.View.OnClickListener
|
||||
import android.widget.Toast
|
||||
import com.bumptech.glide.Glide
|
||||
import com.twitter.Validator
|
||||
import kotlinx.android.synthetic.main.fragment_user_profile_editor.*
|
||||
import nl.komponents.kovenant.combine.and
|
||||
import nl.komponents.kovenant.ui.promiseOnUi
|
||||
import org.mariotaku.abstask.library.AbstractTask
|
||||
import org.mariotaku.abstask.library.TaskStarter
|
||||
import org.mariotaku.ktextension.dismissDialogFragment
|
||||
import org.mariotaku.microblog.library.MicroBlog
|
||||
import org.mariotaku.microblog.library.MicroBlogException
|
||||
import org.mariotaku.microblog.library.mastodon.Mastodon
|
||||
import org.mariotaku.microblog.library.mastodon.model.AccountUpdate
|
||||
import org.mariotaku.microblog.library.twitter.model.ProfileUpdate
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.TwidereConstants.*
|
||||
import org.mariotaku.twidere.activity.ColorPickerDialogActivity
|
||||
import org.mariotaku.twidere.activity.ThemedMediaPickerActivity
|
||||
import org.mariotaku.twidere.annotation.AccountType
|
||||
import org.mariotaku.twidere.extension.loadProfileBanner
|
||||
import org.mariotaku.twidere.extension.loadProfileImage
|
||||
import org.mariotaku.twidere.extension.model.api.toParcelable
|
||||
import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable
|
||||
import org.mariotaku.twidere.extension.model.api.toParcelable
|
||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||
import org.mariotaku.twidere.loader.ParcelableUserLoader
|
||||
|
@ -64,27 +66,18 @@ import org.mariotaku.twidere.task.*
|
|||
import org.mariotaku.twidere.util.*
|
||||
import org.mariotaku.twidere.view.iface.IExtendedView.OnSizeChangedListener
|
||||
|
||||
class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWatcher,
|
||||
class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener,
|
||||
OnClickListener, LoaderCallbacks<SingleResponse<ParcelableUser>>,
|
||||
KeyboardShortcutsHandler.TakeAllKeyboardShortcut {
|
||||
|
||||
private var currentTask: AbstractTask<*, *, UserProfileEditorFragment>? = null
|
||||
private val accountKey: UserKey
|
||||
get() = arguments.getParcelable<UserKey>(EXTRA_ACCOUNT_KEY)
|
||||
get() = arguments.getParcelable(EXTRA_ACCOUNT_KEY)
|
||||
private var user: ParcelableUser? = null
|
||||
private var account: AccountDetails? = null
|
||||
private var userInfoLoaderInitialized: Boolean = false
|
||||
private var getUserInfoCalled: Boolean = false
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence, length: Int, start: Int, end: Int) {
|
||||
}
|
||||
|
||||
override fun onTextChanged(s: CharSequence, length: Int, start: Int, end: Int) {
|
||||
updateDoneButton()
|
||||
}
|
||||
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
}
|
||||
|
||||
override fun onClick(view: View) {
|
||||
val user = user
|
||||
val task = currentTask
|
||||
|
@ -137,10 +130,11 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
|
|||
|
||||
override fun onLoadFinished(loader: Loader<SingleResponse<ParcelableUser>>,
|
||||
data: SingleResponse<ParcelableUser>) {
|
||||
if (data.data != null && data.data.key != null) {
|
||||
displayUser(data.data)
|
||||
} else if (user == null) {
|
||||
val user = data.data ?: this.user ?: run {
|
||||
activity?.finish()
|
||||
return
|
||||
}
|
||||
displayUser(user, data.extras.getParcelable(EXTRA_ACCOUNT))
|
||||
}
|
||||
|
||||
override fun onLoaderReset(loader: Loader<SingleResponse<ParcelableUser>>) {
|
||||
|
@ -180,10 +174,6 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
|
|||
}
|
||||
|
||||
val lengthChecker = TwitterValidatorMETLengthChecker(Validator())
|
||||
editName.addTextChangedListener(this)
|
||||
editDescription.addTextChangedListener(this)
|
||||
editLocation.addTextChangedListener(this)
|
||||
editUrl.addTextChangedListener(this)
|
||||
|
||||
editDescription.setLengthChecker(lengthChecker)
|
||||
|
||||
|
@ -198,13 +188,15 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
|
|||
setLinkColor.setOnClickListener(this)
|
||||
setBackgroundColor.setOnClickListener(this)
|
||||
|
||||
if (savedInstanceState != null && savedInstanceState.getParcelable<Parcelable>(EXTRA_USER) != null) {
|
||||
val user = savedInstanceState.getParcelable<ParcelableUser>(EXTRA_USER)!!
|
||||
displayUser(user)
|
||||
editName.setText(savedInstanceState.getString(EXTRA_NAME, user.name))
|
||||
editLocation.setText(savedInstanceState.getString(EXTRA_LOCATION, user.location))
|
||||
editDescription.setText(savedInstanceState.getString(EXTRA_DESCRIPTION, ParcelableUserUtils.getExpandedDescription(user)))
|
||||
editUrl.setText(savedInstanceState.getString(EXTRA_URL, user.url_expanded))
|
||||
val savedUser = savedInstanceState?.getParcelable<ParcelableUser?>(EXTRA_USER)
|
||||
val savedAccount = savedInstanceState?.getParcelable<AccountDetails?>(EXTRA_ACCOUNT)
|
||||
if (savedInstanceState != null && savedUser != null && savedAccount != null) {
|
||||
displayUser(savedUser, savedAccount)
|
||||
editName.setText(savedInstanceState.getString(EXTRA_NAME, savedUser.name))
|
||||
editLocation.setText(savedInstanceState.getString(EXTRA_LOCATION, savedUser.location))
|
||||
editDescription.setText(savedInstanceState.getString(EXTRA_DESCRIPTION,
|
||||
ParcelableUserUtils.getExpandedDescription(savedUser)))
|
||||
editUrl.setText(savedInstanceState.getString(EXTRA_URL, savedUser.url_expanded))
|
||||
} else {
|
||||
getUserInfo()
|
||||
}
|
||||
|
@ -213,6 +205,7 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
|
|||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
outState.putParcelable(EXTRA_USER, user)
|
||||
outState.putParcelable(EXTRA_ACCOUNT, account)
|
||||
outState.putString(EXTRA_NAME, ParseUtils.parseString(editName.text))
|
||||
outState.putString(EXTRA_DESCRIPTION, ParseUtils.parseString(editDescription.text))
|
||||
outState.putString(EXTRA_LOCATION, ParseUtils.parseString(editLocation.text))
|
||||
|
@ -254,13 +247,11 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
|
|||
REQUEST_PICK_LINK_COLOR -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
linkColor.color = data.getIntExtra(EXTRA_COLOR, 0)
|
||||
updateDoneButton()
|
||||
}
|
||||
}
|
||||
REQUEST_PICK_BACKGROUND_COLOR -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
backgroundColor.color = data.getIntExtra(EXTRA_COLOR, 0)
|
||||
updateDoneButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -272,11 +263,12 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
|
|||
}
|
||||
}
|
||||
|
||||
private fun displayUser(user: ParcelableUser?) {
|
||||
private fun displayUser(user: ParcelableUser?, account: AccountDetails?) {
|
||||
if (!getUserInfoCalled) return
|
||||
getUserInfoCalled = false
|
||||
this.user = user
|
||||
if (user != null) {
|
||||
this.account = account
|
||||
if (user != null && account != null) {
|
||||
progressContainer.visibility = View.GONE
|
||||
editProfileContent.visibility = View.VISIBLE
|
||||
editName.setText(user.name)
|
||||
|
@ -290,18 +282,44 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
|
|||
|
||||
linkColor.color = user.link_color
|
||||
backgroundColor.color = user.background_color
|
||||
if (USER_TYPE_TWITTER_COM == user.key.host) {
|
||||
editProfileBanner.visibility = View.VISIBLE
|
||||
editProfileBackground.visibility = View.GONE
|
||||
} else {
|
||||
editProfileBanner.visibility = View.GONE
|
||||
editProfileBackground.visibility = View.VISIBLE
|
||||
|
||||
var canEditUrl = false
|
||||
var canEditLocation = false
|
||||
var canEditBanner = false
|
||||
var canEditBackground = false
|
||||
var canEditLinkColor = false
|
||||
var canEditBackgroundColor = false
|
||||
|
||||
when (account.type) {
|
||||
AccountType.TWITTER -> {
|
||||
canEditUrl = true
|
||||
canEditLocation = true
|
||||
canEditBanner = true
|
||||
canEditBackground = true
|
||||
canEditLinkColor = true
|
||||
canEditBackgroundColor = true
|
||||
}
|
||||
AccountType.MASTODON -> {
|
||||
canEditBanner = true
|
||||
}
|
||||
AccountType.FANFOU -> {
|
||||
canEditUrl = true
|
||||
canEditLocation = true
|
||||
canEditBackground = true
|
||||
canEditLinkColor = true
|
||||
canEditBackgroundColor = true
|
||||
}
|
||||
}
|
||||
editProfileBanner.visibility = if (canEditBanner) View.VISIBLE else View.GONE
|
||||
editProfileBackground.visibility = if (canEditBackground) View.VISIBLE else View.GONE
|
||||
editUrl.visibility = if (canEditUrl) View.VISIBLE else View.GONE
|
||||
editLocation.visibility = if (canEditLocation) View.VISIBLE else View.GONE
|
||||
setLinkColor.visibility = if (canEditLinkColor) View.VISIBLE else View.GONE
|
||||
setBackgroundColor.visibility = if (canEditBackgroundColor) View.VISIBLE else View.GONE
|
||||
} else {
|
||||
progressContainer.visibility = View.GONE
|
||||
editProfileContent.visibility = View.GONE
|
||||
}
|
||||
updateDoneButton()
|
||||
}
|
||||
|
||||
private fun getUserInfo() {
|
||||
|
@ -340,10 +358,6 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
|
|||
}
|
||||
}
|
||||
|
||||
private fun updateDoneButton() {
|
||||
|
||||
}
|
||||
|
||||
internal class UpdateProfileTaskInternal(
|
||||
fragment: UserProfileEditorFragment,
|
||||
accountKey: UserKey,
|
||||
|
@ -362,11 +376,42 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
|
|||
}
|
||||
|
||||
override fun onExecute(account: AccountDetails, params: Any?): Pair<ParcelableUser, AccountDetails> {
|
||||
val microBlog = account.newMicroBlogInstance(context = context, cls = MicroBlog::class.java)
|
||||
val orig = this.original
|
||||
if (orig != null && !orig.isProfileChanged()) {
|
||||
return Pair(orig, account)
|
||||
}
|
||||
return Pair(when (account.type) {
|
||||
AccountType.MASTODON -> updateMastodonProfile(account)
|
||||
else -> updateMicroBlogProfile(account)
|
||||
}, account)
|
||||
}
|
||||
|
||||
|
||||
override fun onSucceed(callback: UserProfileEditorFragment?, result: Pair<ParcelableUser, AccountDetails>) {
|
||||
if (callback == null) return
|
||||
promiseOnUi {
|
||||
val context = this.callback?.context ?: return@promiseOnUi
|
||||
val (user, account) = result
|
||||
val task = UpdateAccountInfoTask(context)
|
||||
task.params = Pair(account, user)
|
||||
TaskStarter.execute(task)
|
||||
} and callback.executeAfterFragmentResumed { fragment ->
|
||||
fragment.childFragmentManager.dismissDialogFragment(DIALOG_FRAGMENT_TAG)
|
||||
fragment.activity.finish()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun beforeExecute() {
|
||||
super.beforeExecute()
|
||||
callback?.executeAfterFragmentResumed { fragment ->
|
||||
val df = ProgressDialogFragment.show(fragment.childFragmentManager, DIALOG_FRAGMENT_TAG)
|
||||
df.isCancelable = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateMicroBlogProfile(account: AccountDetails): ParcelableUser {
|
||||
val microBlog = account.newMicroBlogInstance(context = context, cls = MicroBlog::class.java)
|
||||
val profileUpdate = ProfileUpdate()
|
||||
profileUpdate.name(HtmlEscapeHelper.escapeBasic(name))
|
||||
profileUpdate.location(HtmlEscapeHelper.escapeBasic(location))
|
||||
|
@ -374,10 +419,17 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
|
|||
profileUpdate.url(url)
|
||||
profileUpdate.linkColor(linkColor)
|
||||
profileUpdate.backgroundColor(backgroundColor)
|
||||
val user = microBlog.updateProfile(profileUpdate)
|
||||
val profileImageSize = context.getString(R.string.profile_image_size)
|
||||
return Pair(user.toParcelable(account, profileImageSize = profileImageSize), account)
|
||||
return microBlog.updateProfile(profileUpdate).toParcelable(account,
|
||||
profileImageSize = profileImageSize)
|
||||
}
|
||||
|
||||
private fun updateMastodonProfile(account: AccountDetails): ParcelableUser {
|
||||
val mastodon = account.newMicroBlogInstance(context = context, cls = Mastodon::class.java)
|
||||
val accountUpdate = AccountUpdate()
|
||||
accountUpdate.displayName(name)
|
||||
accountUpdate.note(HtmlEscapeHelper.escapeBasic(description))
|
||||
return mastodon.updateCredentials(accountUpdate).toParcelable(account)
|
||||
}
|
||||
|
||||
private fun ParcelableUser.isProfileChanged(): Boolean {
|
||||
|
@ -392,33 +444,6 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
|
|||
return false
|
||||
}
|
||||
|
||||
override fun afterExecute(callback: UserProfileEditorFragment?,
|
||||
result: Pair<ParcelableUser, AccountDetails>?, exception: MicroBlogException?) {
|
||||
super.afterExecute(callback, result, exception)
|
||||
|
||||
callback?.executeAfterFragmentResumed { fragment ->
|
||||
fragment.childFragmentManager.dismissDialogFragment(DIALOG_FRAGMENT_TAG)
|
||||
fragment.activity.finish()
|
||||
}
|
||||
}
|
||||
|
||||
override fun beforeExecute() {
|
||||
super.beforeExecute()
|
||||
callback?.executeAfterFragmentResumed { fragment ->
|
||||
val df = ProgressDialogFragment.show(fragment.childFragmentManager, DIALOG_FRAGMENT_TAG)
|
||||
df.isCancelable = false
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSucceed(callback: UserProfileEditorFragment?, result: Pair<ParcelableUser, AccountDetails>) {
|
||||
if (callback == null) return
|
||||
val activity = callback.activity ?: return
|
||||
val (user, account) = result
|
||||
val task = UpdateAccountInfoTask(activity)
|
||||
task.params = Pair(account, user)
|
||||
TaskStarter.execute(task)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val DIALOG_FRAGMENT_TAG = "updating_user_profile"
|
||||
|
@ -511,10 +536,8 @@ class UserProfileEditorFragment : BaseFragment(), OnSizeChangedListener, TextWat
|
|||
|
||||
override fun afterExecute(callback: UserProfileEditorFragment?, result: ParcelableUser?, exception: MicroBlogException?) {
|
||||
super.afterExecute(callback, result, exception)
|
||||
if (result != null) {
|
||||
callback?.displayUser(result)
|
||||
}
|
||||
callback?.setUpdateState(false)
|
||||
callback?.getUserInfo()
|
||||
}
|
||||
|
||||
override fun beforeExecute() {
|
||||
|
|
|
@ -89,7 +89,7 @@ class ParcelableUserLoader(
|
|||
return@firstOrNull false
|
||||
} ?: return SingleResponse()
|
||||
if (!omitIntentExtra && extras != null) {
|
||||
val user = extras.getParcelable<ParcelableUser>(EXTRA_USER)
|
||||
val user = extras.getParcelable<ParcelableUser?>(EXTRA_USER)
|
||||
if (user != null) {
|
||||
val values = ObjectCursor.valuesCreatorFrom(ParcelableUser::class.java).create(user)
|
||||
resolver.insert(CachedUsers.CONTENT_URI, values)
|
||||
|
|
|
@ -29,8 +29,7 @@ class UpdateAccountInfoTask(
|
|||
|
||||
override fun doLongOperation(params: Pair<AccountDetails, ParcelableUser>) {
|
||||
val resolver = context.contentResolver
|
||||
val details = params.first
|
||||
val user = params.second
|
||||
val (details, user) = params
|
||||
if (user.is_cache) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -5,9 +5,11 @@ import android.net.Uri
|
|||
import android.widget.Toast
|
||||
import org.mariotaku.microblog.library.MicroBlog
|
||||
import org.mariotaku.microblog.library.MicroBlogException
|
||||
import org.mariotaku.microblog.library.mastodon.Mastodon
|
||||
import org.mariotaku.microblog.library.mastodon.model.AccountUpdate
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.TwidereConstants.LOGTAG
|
||||
import org.mariotaku.twidere.extension.model.api.toParcelable
|
||||
import org.mariotaku.twidere.annotation.AccountType
|
||||
import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable
|
||||
import org.mariotaku.twidere.extension.model.api.toParcelable
|
||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||
import org.mariotaku.twidere.model.AccountDetails
|
||||
|
@ -32,24 +34,32 @@ open class UpdateProfileBannerImageTask<ResultHandler>(
|
|||
private val profileImageSize = context.getString(R.string.profile_image_size)
|
||||
|
||||
override fun onExecute(account: AccountDetails, params: Any?): ParcelableUser {
|
||||
val microBlog = account.newMicroBlogInstance(context, MicroBlog::class.java)
|
||||
try {
|
||||
UpdateStatusTask.getBodyFromMedia(context, imageUri, ParcelableMedia.Type.IMAGE,
|
||||
return UpdateStatusTask.getBodyFromMedia(context, imageUri, ParcelableMedia.Type.IMAGE,
|
||||
deleteImage, false, null, false, null).use {
|
||||
microBlog.updateProfileBannerImage(it.body)
|
||||
when (account.type) {
|
||||
AccountType.MASTODON -> {
|
||||
val mastodon = account.newMicroBlogInstance(context, Mastodon::class.java)
|
||||
return@use mastodon.updateCredentials(AccountUpdate().header(it.body))
|
||||
.toParcelable(account)
|
||||
}
|
||||
else -> {
|
||||
val microBlog = account.newMicroBlogInstance(context, MicroBlog::class.java)
|
||||
microBlog.updateProfileBannerImage(it.body)
|
||||
// Wait for 5 seconds, see
|
||||
// https://dev.twitter.com/docs/api/1.1/post/account/update_profile_image
|
||||
Thread.sleep(5000L)
|
||||
return@use microBlog.verifyCredentials().toParcelable(account,
|
||||
profileImageSize = profileImageSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
throw MicroBlogException(e)
|
||||
}
|
||||
// Wait for 5 seconds, see
|
||||
// https://dev.twitter.com/docs/api/1.1/post/account/update_profile_image
|
||||
try {
|
||||
Thread.sleep(5000L)
|
||||
} catch (e: InterruptedException) {
|
||||
DebugLog.w(LOGTAG, tr = e)
|
||||
DebugLog.w(tr = e)
|
||||
throw MicroBlogException(e)
|
||||
}
|
||||
val user = microBlog.verifyCredentials()
|
||||
return user.toParcelable(account, profileImageSize = profileImageSize)
|
||||
}
|
||||
|
||||
override fun onSucceed(callback: ResultHandler?, result: ParcelableUser) {
|
||||
|
|
|
@ -5,8 +5,11 @@ import android.net.Uri
|
|||
import android.widget.Toast
|
||||
import org.mariotaku.microblog.library.MicroBlog
|
||||
import org.mariotaku.microblog.library.MicroBlogException
|
||||
import org.mariotaku.microblog.library.mastodon.Mastodon
|
||||
import org.mariotaku.microblog.library.mastodon.model.AccountUpdate
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.TwidereConstants
|
||||
import org.mariotaku.twidere.annotation.AccountType
|
||||
import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable
|
||||
import org.mariotaku.twidere.extension.model.api.toParcelable
|
||||
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
||||
import org.mariotaku.twidere.model.AccountDetails
|
||||
|
@ -31,28 +34,37 @@ open class UpdateProfileImageTask<ResultHandler>(
|
|||
private val profileImageSize = context.getString(R.string.profile_image_size)
|
||||
|
||||
override fun onExecute(account: AccountDetails, params: Any?): ParcelableUser {
|
||||
val microBlog = account.newMicroBlogInstance(context, MicroBlog::class.java)
|
||||
try {
|
||||
UpdateStatusTask.getBodyFromMedia(context, imageUri, ParcelableMedia.Type.IMAGE,
|
||||
return UpdateStatusTask.getBodyFromMedia(context, imageUri, ParcelableMedia.Type.IMAGE,
|
||||
deleteImage, false, null, false, null).use {
|
||||
microBlog.updateProfileImage(it.body)
|
||||
when (account.type) {
|
||||
AccountType.MASTODON -> {
|
||||
val mastodon = account.newMicroBlogInstance(context, Mastodon::class.java)
|
||||
return@use mastodon.updateCredentials(AccountUpdate().avatar(it.body))
|
||||
.toParcelable(account)
|
||||
}
|
||||
else -> {
|
||||
val microBlog = account.newMicroBlogInstance(context, MicroBlog::class.java)
|
||||
microBlog.updateProfileImage(it.body)
|
||||
// Wait for 5 seconds, see
|
||||
// https://dev.twitter.com/docs/api/1.1/post/account/update_profile_image
|
||||
Thread.sleep(5000L)
|
||||
return@use microBlog.verifyCredentials().toParcelable(account,
|
||||
profileImageSize = profileImageSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
throw MicroBlogException(e)
|
||||
}
|
||||
// Wait for 5 seconds, see
|
||||
// https://dev.twitter.com/docs/api/1.1/post/account/update_profile_image
|
||||
try {
|
||||
Thread.sleep(5000L)
|
||||
} catch (e: InterruptedException) {
|
||||
DebugLog.w(TwidereConstants.LOGTAG, tr = e)
|
||||
DebugLog.w(tr = e)
|
||||
throw MicroBlogException(e)
|
||||
}
|
||||
val user = microBlog.verifyCredentials()
|
||||
return user.toParcelable(account, profileImageSize = profileImageSize)
|
||||
}
|
||||
|
||||
override fun onSucceed(callback: ResultHandler?, result: ParcelableUser) {
|
||||
Toast.makeText(context, R.string.message_toast_profile_image_updated, Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(context, R.string.message_toast_profile_image_updated, Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
bus.post(ProfileUpdatedEvent(result))
|
||||
}
|
||||
|
||||
|
|
|
@ -355,7 +355,6 @@ class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View)
|
|||
mediaPreview.visibility = View.GONE
|
||||
}
|
||||
|
||||
|
||||
summaryView.text = status.extras?.summary_text
|
||||
summaryView.hideIfEmpty()
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@
|
|||
<string name="count_label_retweets">من إعادات التغريد</string>
|
||||
<string name="created_by">أنشأها <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">أُنشأت القائمة <xliff:g id="list">%s</xliff:g>.</string>
|
||||
<string name="crop_image">تقطيع الصورة</string>
|
||||
<string name="title_crop_image">تقطيع الصورة</string>
|
||||
<string name="current_status">التغريدة الحالية</string>
|
||||
<string name="custom_host_mapping">تعيين مضيف مخصص</string>
|
||||
<string name="custom_host_mapping_summary">استضافة رسم الخرائط مثل/إلخ/استضافات، ولكن لا تتطلب أية أذونات إضافية.</string>
|
||||
|
|
|
@ -254,7 +254,7 @@
|
|||
<string name="count_label_retweets">Retuits</string>
|
||||
<string name="created_by">Creáu por <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Creóse\'l llistáu «<xliff:g id="list">%s</xliff:g>».</string>
|
||||
<string name="crop_image">Retayar imaxe</string>
|
||||
<string name="title_crop_image">Retayar imaxe</string>
|
||||
<string name="current_status">Tuit actual</string>
|
||||
<string name="custom_host_mapping">Mapeáu d\'agospiu personalizáu</string>
|
||||
<string name="custom_host_mapping_summary">Mapeáu d\'agospiu como /etc/hosts, pero nun rique permisu adicional dalu.</string>
|
||||
|
|
|
@ -169,7 +169,7 @@
|
|||
<string name="count_label_retweets">Repiulades</string>
|
||||
<string name="created_by">Creat per <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Heu creat la llista «<xliff:g id="list">%s</xliff:g>».</string>
|
||||
<string name="crop_image">Retallar imatge</string>
|
||||
<string name="title_crop_image">Retallar imatge</string>
|
||||
<string name="current_status">Piulada actual</string>
|
||||
<string name="custom_host_mapping">Associacions de servidors personalitzades</string>
|
||||
<string name="custom_host_mapping_summary">Associa servidors com el fitxer /etc/hosts sense requerir permisos addicionals.</string>
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
<!-- [noun] Count label for retweets, e.g. (N retweets)-->
|
||||
<string name="count_label_retweets">Retweety</string>
|
||||
<string name="created_by">Vytvořil(a) <xliff:g id="created_by">%s </xliff:g></string>
|
||||
<string name="crop_image">Oříznout obrázek</string>
|
||||
<string name="title_crop_image">Oříznout obrázek</string>
|
||||
<string name="current_status">Aktuální tweet</string>
|
||||
<string name="dark_theme">Tmavý motiv</string>
|
||||
<string name="default_account">Výchozí účet</string>
|
||||
|
|
|
@ -254,7 +254,7 @@
|
|||
<string name="count_label_retweets">Retweets</string>
|
||||
<string name="created_by">Erstellt von <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Liste \"<xliff:g id="list">%s</xliff:g>\" erstellt.</string>
|
||||
<string name="crop_image">Bild zurechtschneiden</string>
|
||||
<string name="title_crop_image">Bild zurechtschneiden</string>
|
||||
<string name="current_status">Aktueller Tweet</string>
|
||||
<string name="custom_host_mapping">Individuelles Host-Mapping</string>
|
||||
<string name="custom_host_mapping_summary">Host-Mapping wie /ect/hosts, ohne zusätzlich erforderliche Rechte.</string>
|
||||
|
|
|
@ -255,7 +255,7 @@
|
|||
<string name="count_label_retweets">Retweets</string>
|
||||
<string name="created_by">Creado por <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">La lista \"<xliff:g id="list">%s</xliff:g>\" ha sido creada.</string>
|
||||
<string name="crop_image">Cortar imagen</string>
|
||||
<string name="title_crop_image">Cortar imagen</string>
|
||||
<string name="current_status">Tweet actual</string>
|
||||
<string name="custom_host_mapping">Asignación de host personalizado</string>
|
||||
<string name="custom_host_mapping_summary">Funciona como \"/etc/hosts\", pero no requiere permisos adicionales.</string>
|
||||
|
|
|
@ -203,7 +203,7 @@
|
|||
<string name="count_label_retweets">بازتوییتها</string>
|
||||
<string name="created_by">ایجاد شده توسّط <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">فهرست «<xliff:g id="list">%s</xliff:g>» را ساخت.</string>
|
||||
<string name="crop_image">بریدن تصویر</string>
|
||||
<string name="title_crop_image">بریدن تصویر</string>
|
||||
<string name="current_status">توییت جاری</string>
|
||||
<string name="custom_host_mapping">مسیردهی میزبان سفارشی</string>
|
||||
<string name="custom_host_mapping_summary">مسیردهی میزبان مانند etc/hosts/، اما بدون نیاز به هرگونه دسترسی اضافی.</string>
|
||||
|
|
|
@ -173,7 +173,7 @@
|
|||
<string name="count_label_retweets">Uudelleentwiittaukset</string>
|
||||
<string name="created_by">Luoja <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Luotiin lista \"<xliff:g id="list">%s</xliff:g>\".</string>
|
||||
<string name="crop_image">Rajaa kuva</string>
|
||||
<string name="title_crop_image">Rajaa kuva</string>
|
||||
<string name="current_status">Nykyinen twiitti</string>
|
||||
<string name="custom_host_mapping">Mukautettu Host Mapping -määrittely</string>
|
||||
<string name="custom_host_mapping_summary">Verkkonimet määritellään kuten /etc/hosts -tiedostossa, mutta ylimääräisiä oikeuksia ei tarvita.</string>
|
||||
|
|
|
@ -254,7 +254,7 @@
|
|||
<string name="count_label_retweets">Retweets</string>
|
||||
<string name="created_by">Créé par <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Liste \"<xliff:g id="list">%s</xliff:g>\" créée.</string>
|
||||
<string name="crop_image">Rogner l\'image</string>
|
||||
<string name="title_crop_image">Rogner l\'image</string>
|
||||
<string name="current_status">Tweet en cours</string>
|
||||
<string name="custom_host_mapping">Mappage d\'hôte personnalisée</string>
|
||||
<string name="custom_host_mapping_summary">Mappage d\'hôte comme /etc/hosts, mais n\'exige pas de permissions supplémentaires.</string>
|
||||
|
|
|
@ -255,7 +255,7 @@
|
|||
<string name="count_label_retweets">Rechouchíos</string>
|
||||
<string name="created_by">Creado por <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Creada a lista \"<xliff:g id="list">%s</xliff:g>\".</string>
|
||||
<string name="crop_image">Recortar imaxe</string>
|
||||
<string name="title_crop_image">Recortar imaxe</string>
|
||||
<string name="current_status">Chío actual</string>
|
||||
<string name="custom_host_mapping">Personalizar host mapping</string>
|
||||
<string name="custom_host_mapping_summary">Host mapping coma /etc/hosts, pero non require ningún permiso adicional.</string>
|
||||
|
|
|
@ -150,7 +150,7 @@
|
|||
<string name="count_label_retweets">Retweetovi</string>
|
||||
<string name="created_by">Stvorio <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Stvorena lista \"<xliff:g id="list">%s</xliff:g>\".</string>
|
||||
<string name="crop_image">Obreži sliku</string>
|
||||
<string name="title_crop_image">Obreži sliku</string>
|
||||
<string name="custom_host_mapping">Mapiranje prilagođenog domaćina</string>
|
||||
<string name="custom_host_mapping_summary">Mapiranje domaćina poput /npr/domaćini, ali ne zahtijeva dodatna dopuštenja.</string>
|
||||
<string name="dark_theme">Tamna tema</string>
|
||||
|
|
|
@ -183,7 +183,7 @@
|
|||
<string name="count_label_retweets">Retweet</string>
|
||||
<string name="created_by">Létrehozta: <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">\"<xliff:g id="list">%s</xliff:g>\" lista létrehozva.</string>
|
||||
<string name="crop_image">Kép vágása</string>
|
||||
<string name="title_crop_image">Kép vágása</string>
|
||||
<string name="current_status">Jelenlegi tweet</string>
|
||||
<string name="custom_host_mapping">Egyedi host hozzárendelés</string>
|
||||
<string name="custom_host_mapping_summary">Host hozzárendelés, mint a /etc/hosts, de nem kell hozzá plusz jog.</string>
|
||||
|
|
|
@ -183,7 +183,7 @@
|
|||
<string name="count_label_retweets">Retweets</string>
|
||||
<string name="created_by">Dibuat oleh <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Membuat daftar \"<xliff:g id="list">%s</xliff:g>\".</string>
|
||||
<string name="crop_image">Potong gambar</string>
|
||||
<string name="title_crop_image">Potong gambar</string>
|
||||
<string name="current_status">Twit sekarang</string>
|
||||
<string name="custom_host_mapping">Kustom host mapping</string>
|
||||
<string name="custom_host_mapping_summary">Host pemetaan sperti /etc/hosts, tanpa butuh permisi tambahan.</string>
|
||||
|
|
|
@ -168,7 +168,7 @@
|
|||
<string name="count_label_retweets">Retweet</string>
|
||||
<string name="created_by">Creato da <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Lista creata \"<xliff:g id="list">%s</xliff:g>\".</string>
|
||||
<string name="crop_image">Ritaglia immagine</string>
|
||||
<string name="title_crop_image">Ritaglia immagine</string>
|
||||
<string name="current_status">Tweet corrente</string>
|
||||
<string name="custom_host_mapping">Mappatura host personalizzata</string>
|
||||
<string name="custom_host_mapping_summary">Mappa gli host come in /etc/hosts, ma non richiede permessi aggiuntivi.</string>
|
||||
|
|
|
@ -255,7 +255,7 @@
|
|||
<string name="count_label_retweets">リツイート</string>
|
||||
<string name="created_by"><xliff:g id="created_by">%s</xliff:g>により作成</string>
|
||||
<string name="created_list">リスト\"<xliff:g id="list">%s</xliff:g>\"を作成しました。</string>
|
||||
<string name="crop_image">トリミング</string>
|
||||
<string name="title_crop_image">トリミング</string>
|
||||
<string name="current_status">現在のツイート</string>
|
||||
<string name="custom_host_mapping">ホストマッピングの設定</string>
|
||||
<string name="custom_host_mapping_summary">rootedでなくても/etc/hostsのようにホストマッピングができます。</string>
|
||||
|
|
|
@ -217,7 +217,7 @@
|
|||
<string name="count_label_retweets">리트윗</string>
|
||||
<string name="created_by"><xliff:g id="created_by">%s</xliff:g>님이 만듦</string>
|
||||
<string name="created_list">\"<xliff:g id="list">%s</xliff:g>\" 리스트를 만들었습니다.</string>
|
||||
<string name="crop_image">이미지 자르기</string>
|
||||
<string name="title_crop_image">이미지 자르기</string>
|
||||
<string name="current_status">현재 트윗</string>
|
||||
<string name="custom_host_mapping">커스텀 호스트 매핑</string>
|
||||
<string name="custom_host_mapping_summary">/etc/hosts 에 지정하는 것처럼 호스트를 매핑합니다. 다른 권한은 전혀 필요 없습니다.</string>
|
||||
|
|
|
@ -168,7 +168,7 @@
|
|||
<string name="count_label_retweets">Retweets</string>
|
||||
<string name="created_by">Gemaakt door <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">\'\'<xliff:g id="list">%s</xliff:g>\'\' lijst aangemaakt.</string>
|
||||
<string name="crop_image">Afbeelding bijsnijden</string>
|
||||
<string name="title_crop_image">Afbeelding bijsnijden</string>
|
||||
<string name="current_status">Huidige tweet</string>
|
||||
<string name="custom_host_mapping">Aangepaste host toewijzingen</string>
|
||||
<string name="custom_host_mapping_summary">Host toewijzingen zoals /etc/hosts, maar heeft geen aanvullende rechten nodig.</string>
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
<string name="count_label_retweets">Retweets</string>
|
||||
<string name="created_by">Opprettet av <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Opprettet listen «<xliff:g id="list">%s</xliff:g>».</string>
|
||||
<string name="crop_image">Beskjær bilde</string>
|
||||
<string name="title_crop_image">Beskjær bilde</string>
|
||||
<string name="current_status">Gjeldende tweet</string>
|
||||
<string name="custom_host_mapping">Tilpasset vertskobling</string>
|
||||
<string name="custom_host_mapping_summary">Vertskobling som /etc/hosts, men krever ingen ekstra tillatelser.</string>
|
||||
|
|
|
@ -196,7 +196,7 @@
|
|||
<string name="count_label_retweets">Retweets</string>
|
||||
<string name="created_by">Criada por <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">A lista \"<xliff:g id="list">%s</xliff:g>\" foi criada.</string>
|
||||
<string name="crop_image">Cortar imagem</string>
|
||||
<string name="title_crop_image">Cortar imagem</string>
|
||||
<string name="current_status">Tweet atual</string>
|
||||
<string name="custom_host_mapping">Mapeamento de hosts personalizado</string>
|
||||
<string name="custom_host_mapping_summary">Mapear hosts tais como /etc/hosts, mas não requer outras permissões adicionais.</string>
|
||||
|
|
|
@ -189,7 +189,7 @@
|
|||
<string name="count_label_retweets">Ретвиты</string>
|
||||
<string name="created_by">Создано пользователем <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Созданный список \"<xliff:g id="list">%s</xliff:g>\".</string>
|
||||
<string name="crop_image">Обрезать изображение</string>
|
||||
<string name="title_crop_image">Обрезать изображение</string>
|
||||
<string name="current_status">Текущий твит</string>
|
||||
<string name="custom_host_mapping">Перенаправление узлов</string>
|
||||
<string name="custom_host_mapping_summary">Перенаправление узлов, как с помощью /etc/hosts, но не требующее дополнительных разрешений.</string>
|
||||
|
|
|
@ -255,7 +255,7 @@
|
|||
<string name="count_label_retweets">Retweets</string>
|
||||
<string name="created_by">Skapad av <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Skapade listan \"<xliff:g id="list">%s</xliff:g>\".</string>
|
||||
<string name="crop_image">Beskär bild</string>
|
||||
<string name="title_crop_image">Beskär bild</string>
|
||||
<string name="current_status">Nuvarande tweet</string>
|
||||
<string name="custom_host_mapping">Anpassad värdmappning</string>
|
||||
<string name="custom_host_mapping_summary">Värdmappning som exempelvis /etc/hosts, men som inte kräver ytterligare rättigheter.</string>
|
||||
|
|
|
@ -255,7 +255,7 @@
|
|||
<string name="count_label_retweets">รีทวีต</string>
|
||||
<string name="created_by">สร้างโดย <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">สร้างลิสต์ \"<xliff:g id="list">%s</xliff:g>\" แล้ว</string>
|
||||
<string name="crop_image">ตัดรูปภาพ</string>
|
||||
<string name="title_crop_image">ตัดรูปภาพ</string>
|
||||
<string name="current_status">ทวีตปัจจุบัน</string>
|
||||
<string name="custom_host_mapping">กำหนดที่อยู่ host เอง</string>
|
||||
<string name="custom_host_mapping_summary">กำหนดที่อยู่ host เอง (เหมือนในไฟล์ /etc/hosts) ซึ่งการกระทำนี้ไม่ต้องการสิทธิ์ใดๆ เพิ่มเติม</string>
|
||||
|
|
|
@ -171,7 +171,7 @@
|
|||
<string name="count_label_retweets">Retweetler</string>
|
||||
<string name="created_by"><xliff:g id="created_by">%s</xliff:g> tarafından oluşturuldu</string>
|
||||
<string name="created_list"><xliff:g id="list">%s</xliff:g> listesi oluşturuldu.</string>
|
||||
<string name="crop_image">Görüntüyü kırp</string>
|
||||
<string name="title_crop_image">Görüntüyü kırp</string>
|
||||
<string name="current_status">Güncel tweet</string>
|
||||
<string name="custom_host_mapping">Özel sunucu haritalama</string>
|
||||
<string name="custom_host_mapping_summary">/etc/hosts şeklinde sunucu haritalama, ancak ekstra izin gerektirmez.</string>
|
||||
|
|
|
@ -172,7 +172,7 @@
|
|||
<string name="count_label_retweets">Ретвіти</string>
|
||||
<string name="created_by">Створено <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Створено список \"<xliff:g id="list">%s</xliff:g>\".</string>
|
||||
<string name="crop_image">Обрізати зображення</string>
|
||||
<string name="title_crop_image">Обрізати зображення</string>
|
||||
<string name="current_status">Поточний твіт</string>
|
||||
<string name="custom_host_mapping">Перенаправлення вузлів</string>
|
||||
<string name="custom_host_mapping_summary">Перенаправлення вузлів, як за допомогою /etc/hosts, але не потребує додаткових дозволів.</string>
|
||||
|
|
|
@ -255,7 +255,7 @@
|
|||
<string name="count_label_retweets">转推</string>
|
||||
<string name="created_by">由 <xliff:g id="created_by">%s</xliff:g> 创建</string>
|
||||
<string name="created_list">创建了列表 “<xliff:g id="list">%s</xliff:g>”</string>
|
||||
<string name="crop_image">裁剪图像</string>
|
||||
<string name="title_crop_image">裁剪图像</string>
|
||||
<string name="current_status">当前推文</string>
|
||||
<string name="custom_host_mapping">自定义主机映射</string>
|
||||
<string name="custom_host_mapping_summary">如同 /etc/hosts 的主机映射,但不需要任何额外的权限</string>
|
||||
|
|
|
@ -255,7 +255,7 @@
|
|||
<string name="count_label_retweets">轉推</string>
|
||||
<string name="created_by">由<xliff:g id="created_by">%s</xliff:g>創建</string>
|
||||
<string name="created_list">建立了列表 \"<xliff:g id="list">%s</xliff:g>\"</string>
|
||||
<string name="crop_image">裁剪圖片</string>
|
||||
<string name="title_crop_image">裁剪圖片</string>
|
||||
<string name="current_status">當前推文</string>
|
||||
<string name="custom_host_mapping">自訂主機對應</string>
|
||||
<string name="custom_host_mapping_summary">如同/etc/hosts的主機對應,但不需要任何額外的權限</string>
|
||||
|
|
|
@ -255,7 +255,7 @@
|
|||
<string name="count_label_retweets">轉推</string>
|
||||
<string name="created_by">由<xliff:g id="created_by">%s</xliff:g>創建</string>
|
||||
<string name="created_list">建立了列表 \"<xliff:g id="list">%s</xliff:g>\"</string>
|
||||
<string name="crop_image">裁剪圖片</string>
|
||||
<string name="title_crop_image">裁剪圖片</string>
|
||||
<string name="current_status">當前推文</string>
|
||||
<string name="custom_host_mapping">自訂主機對應</string>
|
||||
<string name="custom_host_mapping_summary">如同/etc/hosts的主機對應,但不需要任何額外的權限</string>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.theartofdev.edmodo.cropper.CropImageView
|
||||
android:id="@+id/cropImageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
</RelativeLayout>
|
|
@ -1,55 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.soundcloud.android.crop.CropImageView
|
||||
android:id="@+id/crop_image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/done_cancel_bar"
|
||||
android:background="@drawable/crop__texture"/>
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/done_cancel_bar"
|
||||
style="?attr/actionBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?actionBarSize"
|
||||
android:layout_alignParentTop="true"
|
||||
android:touchscreenBlocksFocus="true"
|
||||
app:contentInsetEnd="0dp"
|
||||
app:contentInsetStart="0dp"
|
||||
tools:ignore="UnusedAttribute">
|
||||
|
||||
<include layout="@layout/layout_image_cropper_done_cancel"/>
|
||||
</android.support.v7.widget.Toolbar>
|
||||
|
||||
<View
|
||||
android:id="@+id/window_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/done_cancel_bar"
|
||||
android:background="?android:windowContentOverlay"/>
|
||||
</RelativeLayout>
|
|
@ -25,7 +25,7 @@
|
|||
android:orientation="horizontal">
|
||||
|
||||
<org.mariotaku.twidere.view.FixedTextView
|
||||
android:id="@+id/btn_cancel"
|
||||
android:id="@+id/btnCancel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
|
@ -37,7 +37,7 @@
|
|||
android:textStyle="bold"/>
|
||||
|
||||
<org.mariotaku.twidere.view.FixedTextView
|
||||
android:id="@+id/btn_done"
|
||||
android:id="@+id/btnDone"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Twidere - Twitter client for Android
|
||||
~
|
||||
~ Copyright (C) 2012-2017 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/>.
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/perform_crop"
|
||||
android:icon="@drawable/ic_action_confirm"
|
||||
android:title="@android:string/ok"
|
||||
app:showAsAction="always"/>
|
||||
</menu>
|
|
@ -297,8 +297,6 @@
|
|||
<string name="created_by">Created by <xliff:g id="created_by">%s</xliff:g></string>
|
||||
<string name="created_list">Created list \"<xliff:g id="list">%s</xliff:g>\".</string>
|
||||
|
||||
<string name="crop_image">Crop image</string>
|
||||
|
||||
<string name="current_status">Current tweet</string>
|
||||
|
||||
<string name="custom_host_mapping">Custom host mapping</string>
|
||||
|
@ -1197,6 +1195,7 @@
|
|||
<string name="title_buffer_settings">Buffer settings</string>
|
||||
<string name="title_compose">Compose</string>
|
||||
<string name="title_conversation">Conversation</string>
|
||||
<string name="title_crop_image">Crop image</string>
|
||||
<string name="title_dialog_sync_connect_to">Connect to…</string>
|
||||
<string name="title_direct_messages">Messages</string>
|
||||
<string name="title_direct_messages_conversation_info">Conversation info</string>
|
||||
|
|
Loading…
Reference in New Issue