diff --git a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/TwitterUpload.java b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/TwitterUpload.java index be4f5cb7b..50ced2880 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/TwitterUpload.java +++ b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/TwitterUpload.java @@ -19,6 +19,7 @@ package org.mariotaku.microblog.library.twitter; import org.mariotaku.microblog.library.MicroBlogException; +import org.mariotaku.microblog.library.twitter.annotation.MediaCategory; import org.mariotaku.microblog.library.twitter.model.MediaUploadResponse; import org.mariotaku.microblog.library.twitter.model.NewMediaMetadata; import org.mariotaku.microblog.library.twitter.model.ResponseCode; @@ -46,7 +47,7 @@ public interface TwitterUpload { @Params(@KeyValue(key = "command", value = "INIT")) MediaUploadResponse initUploadMedia(@Param("media_type") String mediaType, @Param("total_bytes") long totalBytes, - @Param("media_category") String mediaCategory, + @MediaCategory @Param("media_category") String mediaCategory, @Param(value = "additional_owners", arrayDelimiter = ',') String[] additionalOwners) throws MicroBlogException; diff --git a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/annotation/MediaCategory.java b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/annotation/MediaCategory.java new file mode 100644 index 000000000..efac472df --- /dev/null +++ b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/annotation/MediaCategory.java @@ -0,0 +1,36 @@ +/* + * Twidere - Twitter client for Android + * + * Copyright 2012-2017 Mariotaku Lee + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.mariotaku.microblog.library.twitter.annotation; + +import android.support.annotation.StringDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.SOURCE) +@StringDef({MediaCategory.TWEET_IMAGE, MediaCategory.TWEET_GIF, MediaCategory.TWEET_VIDEO, + MediaCategory.DM_IMAGE, MediaCategory.DM_GIF, MediaCategory.DM_VIDEO}) +public @interface MediaCategory { + String TWEET_IMAGE = "tweet_image"; + String TWEET_GIF = "tweet_gif"; + String TWEET_VIDEO = "tweet_video"; + String DM_IMAGE = "dm_image"; + String DM_GIF = "dm_gif"; + String DM_VIDEO = "dm_video"; +} diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/account/AccountExtras.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/account/AccountExtras.java index ecd3fb9ff..5e8cae2d4 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/model/account/AccountExtras.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/model/account/AccountExtras.java @@ -20,10 +20,13 @@ package org.mariotaku.twidere.model.account; import android.os.Parcelable; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import com.bluelinelabs.logansquare.annotation.JsonField; import com.bluelinelabs.logansquare.annotation.JsonObject; +import org.mariotaku.microblog.library.twitter.annotation.MediaCategory; + /** * Created by mariotaku on 16/2/26. */ @@ -74,6 +77,22 @@ public interface AccountExtras extends Parcelable { this.maxSizeAsync = maxSizeAsync; } + public boolean checkSize(long size, boolean async) { + final long limit = async ? getMaxSizeAsync() : getMaxSizeSync(); + if (limit <= 0 || size <= 0) return true; + return size <= limit; + } + + @Override + public String toString() { + return "ImageLimit{" + + "maxWidth=" + maxWidth + + ", maxHeight=" + maxHeight + + ", maxSizeSync=" + maxSizeSync + + ", maxSizeAsync=" + maxSizeAsync + + '}'; + } + @NonNull public static ImageLimit ofSize(int width, int height) { final ImageLimit limit = new ImageLimit(); @@ -82,10 +101,18 @@ public interface AccountExtras extends Parcelable { return limit; } - public boolean checkSize(long size, boolean async) { - final long limit = async ? getMaxSizeAsync() : getMaxSizeSync(); - if (limit <= 0 || size <= 0) return true; - return size <= limit; + @NonNull + public static ImageLimit twitterDefault(@Nullable @MediaCategory String category) { + if (MediaCategory.DM_IMAGE.equals(category)) { + ImageLimit limit = new ImageLimit(); + limit.setMaxSizeSync(5 * 1024 * 1024); + limit.setMaxSizeAsync(5 * 1024 * 1024); + return limit; + } + final ImageLimit limit = new ImageLimit(); + limit.setMaxSizeSync(3 * 1024 * 1024); + limit.setMaxSizeAsync(3 * 1024 * 1024); + return limit; } } @@ -320,6 +347,28 @@ public interface AccountExtras extends Parcelable { return true; } + @Override + public String toString() { + return "VideoLimit{" + + "supported=" + supported + + ", minWidth=" + minWidth + + ", minHeight=" + minHeight + + ", maxWidth=" + maxWidth + + ", maxHeight=" + maxHeight + + ", canRotateGeometryLimit=" + canRotateGeometryLimit + + ", maxSizeSync=" + maxSizeSync + + ", maxSizeAsync=" + maxSizeAsync + + ", minAspectRatio=" + minAspectRatio + + ", maxAspectRatio=" + maxAspectRatio + + ", minFrameRate=" + minFrameRate + + ", maxFrameRate=" + maxFrameRate + + ", minDurationSync=" + minDurationSync + + ", minDurationAsync=" + minDurationAsync + + ", maxDurationSync=" + maxDurationSync + + ", maxDurationAsync=" + maxDurationAsync + + '}'; + } + public static VideoLimit twitterDefault() { VideoLimit videoLimit = new VideoLimit(); videoLimit.setSupported(true); diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/BitmapFactoryExtensions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/BitmapFactoryExtensions.kt index ab7ed1e59..6ce1bda86 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/BitmapFactoryExtensions.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/BitmapFactoryExtensions.kt @@ -6,6 +6,9 @@ fun BitmapFactory.Options.calculateInSampleSize(preferredWidth: Int, preferredHe if (preferredHeight > outHeight && preferredWidth > outWidth) { return 1 } + if (preferredHeight <= 0 && preferredWidth <= 0) { + return 1 + } val result = Math.round(Math.max(outWidth, outHeight) / Math.max(preferredWidth, preferredHeight).toFloat()) return Math.max(1, result) } \ No newline at end of file diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/AccountDetailsExtensions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/AccountDetailsExtensions.kt index 85931cd25..75f627427 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/AccountDetailsExtensions.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/AccountDetailsExtensions.kt @@ -2,6 +2,7 @@ package org.mariotaku.twidere.extension.model import android.content.Context import com.twitter.Validator +import org.mariotaku.microblog.library.twitter.annotation.MediaCategory import org.mariotaku.twidere.annotation.AccountType import org.mariotaku.twidere.model.AccountDetails import org.mariotaku.twidere.model.account.AccountExtras @@ -41,34 +42,33 @@ fun AccountDetails.newMicroBlogInstance(context: Context, cls: Class): T val AccountDetails.isOAuth: Boolean get() = credentials_type == Credentials.Type.OAUTH || credentials_type == Credentials.Type.XAUTH -val AccountDetails.mediaSizeLimit: UpdateStatusTask.SizeLimit? - get() { - when (type) { - AccountType.TWITTER -> { - val imageLimit = AccountExtras.ImageLimit.ofSize(2048, 1536) - val videoLimit = AccountExtras.VideoLimit.twitterDefault() - return UpdateStatusTask.SizeLimit(imageLimit, videoLimit) - } - AccountType.FANFOU -> { - val imageLimit = AccountExtras.ImageLimit.ofSize(2048, 1536) - val videoLimit = AccountExtras.VideoLimit.unsupported() - return UpdateStatusTask.SizeLimit(imageLimit, videoLimit) - } - AccountType.STATUSNET -> { - val extras = extras as? StatusNetAccountExtras ?: return null - val imageLimit = AccountExtras.ImageLimit().apply { - maxSizeSync = extras.uploadLimit - maxSizeAsync = extras.uploadLimit - } - val videoLimit = AccountExtras.VideoLimit().apply { - maxSizeSync = extras.uploadLimit - maxSizeAsync = extras.uploadLimit - } - return UpdateStatusTask.SizeLimit(imageLimit, videoLimit) - } - else -> return null +fun AccountDetails.getMediaSizeLimit(@MediaCategory mediaCategory: String? = null): UpdateStatusTask.SizeLimit? { + when (type) { + AccountType.TWITTER -> { + val imageLimit = AccountExtras.ImageLimit.twitterDefault(mediaCategory) + val videoLimit = AccountExtras.VideoLimit.twitterDefault() + return UpdateStatusTask.SizeLimit(imageLimit, videoLimit) } + AccountType.FANFOU -> { + val imageLimit = AccountExtras.ImageLimit.ofSize(2048, 1536) + val videoLimit = AccountExtras.VideoLimit.unsupported() + return UpdateStatusTask.SizeLimit(imageLimit, videoLimit) + } + AccountType.STATUSNET -> { + val extras = extras as? StatusNetAccountExtras ?: return null + val imageLimit = AccountExtras.ImageLimit().apply { + maxSizeSync = extras.uploadLimit + maxSizeAsync = extras.uploadLimit + } + val videoLimit = AccountExtras.VideoLimit().apply { + maxSizeSync = extras.uploadLimit + maxSizeAsync = extras.uploadLimit + } + return UpdateStatusTask.SizeLimit(imageLimit, videoLimit) + } + else -> return null } +} /** * Text limit when composing a status, 0 for no limit diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/task/twitter/UpdateStatusTask.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/task/twitter/UpdateStatusTask.kt index a8dce1353..e43779d4d 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/task/twitter/UpdateStatusTask.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/task/twitter/UpdateStatusTask.kt @@ -43,7 +43,7 @@ import org.mariotaku.twidere.extension.calculateInSampleSize import org.mariotaku.twidere.extension.model.api.mastodon.toParcelable import org.mariotaku.twidere.extension.model.api.toParcelable import org.mariotaku.twidere.extension.model.applyUpdateStatus -import org.mariotaku.twidere.extension.model.mediaSizeLimit +import org.mariotaku.twidere.extension.model.getMediaSizeLimit import org.mariotaku.twidere.extension.model.newMicroBlogInstance import org.mariotaku.twidere.extension.model.textLimit import org.mariotaku.twidere.extension.text.twitter.getTweetLength @@ -305,7 +305,7 @@ class UpdateStatusTask( if (statusUpdate.media.isNotNullOrEmpty()) { // Fanfou only allow one photo fanfouUpdateStatusWithPhoto(microBlog, statusUpdate, pendingUpdate, - account.mediaSizeLimit, i) + account.getMediaSizeLimit(), i) } else { twitterUpdateStatus(microBlog, statusUpdate, pendingUpdate, i) } @@ -712,7 +712,7 @@ class UpdateStatusTask( //noinspection TryWithIdenticalCatches var body: MediaStreamBody? = null try { - val sizeLimit = account.mediaSizeLimit + val sizeLimit = account.getMediaSizeLimit(mediaCategory) body = getBodyFromMedia(context, media, sizeLimit, chucked, ContentLengthInputStream.ReadListener { length, position -> callback?.onUploadingProgressChanged(index, position, length) @@ -758,7 +758,7 @@ class UpdateStatusTask( //noinspection TryWithIdenticalCatches var body: MediaStreamBody? = null try { - val sizeLimit = account.mediaSizeLimit + val sizeLimit = account.getMediaSizeLimit() body = getBodyFromMedia(context, media, sizeLimit, chucked, ContentLengthInputStream.ReadListener { length, position -> callback?.onUploadingProgressChanged(index, position, length) @@ -931,7 +931,7 @@ class UpdateStatusTask( when (mediaType) { "image/png", "image/x-png", "image/webp", "image-x-webp" -> { tempFile.outputStream().use { os -> - bitmap.compress(Bitmap.CompressFormat.PNG, 0, os) + bitmap.compress(Bitmap.CompressFormat.PNG, 100, os) } } "image/jpeg" -> { @@ -939,6 +939,7 @@ class UpdateStatusTask( .use(::ExifInterface) tempFile.outputStream().use { os -> bitmap.compress(Bitmap.CompressFormat.JPEG, 85, os) + os.flush() } val orientation = origExif.getAttribute(ExifInterface.TAG_ORIENTATION) if (orientation != null) { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/task/twitter/message/SendMessageTask.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/task/twitter/message/SendMessageTask.kt index f12f599b5..9f9095913 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/task/twitter/message/SendMessageTask.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/task/twitter/message/SendMessageTask.kt @@ -24,6 +24,7 @@ import org.mariotaku.ktextension.isNotNullOrEmpty import org.mariotaku.microblog.library.MicroBlog import org.mariotaku.microblog.library.MicroBlogException import org.mariotaku.microblog.library.twitter.TwitterUpload +import org.mariotaku.microblog.library.twitter.annotation.MediaCategory import org.mariotaku.microblog.library.twitter.model.DirectMessage import org.mariotaku.microblog.library.twitter.model.NewDm import org.mariotaku.sqliteqb.library.Expression @@ -143,9 +144,9 @@ class SendMessageTask( message: ParcelableNewMessage): GetMessagesTask.DatabaseUpdateData { val recipientId = message.recipient_ids.singleOrNull() ?: throw MicroBlogException("No recipient") val category = when (message.media?.firstOrNull()?.type) { - ParcelableMedia.Type.IMAGE -> "dm_image" - ParcelableMedia.Type.VIDEO -> "dm_video" - ParcelableMedia.Type.ANIMATED_GIF -> "dm_gif" + ParcelableMedia.Type.IMAGE -> MediaCategory.DM_IMAGE + ParcelableMedia.Type.VIDEO -> MediaCategory.DM_VIDEO + ParcelableMedia.Type.ANIMATED_GIF -> MediaCategory.DM_GIF else -> null } val response = uploadMediaThen(account, message, category) { mediaId ->