diff --git a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/fanfou/FanfouStream.java b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/fanfou/FanfouStream.java deleted file mode 100644 index 98b0d0cd87..0000000000 --- a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/fanfou/FanfouStream.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.fanfou; - -import org.mariotaku.microblog.library.fanfou.callback.FanfouUserStreamCallback; -import org.mariotaku.restfu.annotation.method.GET; - -/** - * Created by mariotaku on 2017/3/11. - */ - -public interface FanfouStream { - @GET("/1/user.json") - void getUserStream(FanfouUserStreamCallback callback); -} diff --git a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/fanfou/callback/FanfouUserStreamCallback.java b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/fanfou/callback/FanfouUserStreamCallback.java deleted file mode 100644 index 6a829ccb88..0000000000 --- a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/fanfou/callback/FanfouUserStreamCallback.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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.fanfou.callback; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.text.TextUtils; - -import org.mariotaku.microblog.library.MicroBlogException; -import org.mariotaku.microblog.library.fanfou.model.FanfouStreamObject; -import org.mariotaku.microblog.library.twitter.model.Status; -import org.mariotaku.microblog.library.twitter.model.User; -import org.mariotaku.microblog.library.util.CRLFLineReader; -import org.mariotaku.restfu.callback.RawCallback; -import org.mariotaku.restfu.http.HttpResponse; -import org.mariotaku.twidere.util.JsonSerializer; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.Date; - -/** - * Created by mariotaku on 15/5/26. - */ -@SuppressWarnings({"WeakerAccess"}) -public abstract class FanfouUserStreamCallback implements RawCallback { - - private boolean connected; - - private boolean disconnected; - - @Override - public final void result(@NonNull final HttpResponse response) throws MicroBlogException, IOException { - if (!response.isSuccessful()) { - final MicroBlogException cause = new MicroBlogException(); - cause.setHttpResponse(response); - onException(cause); - return; - } - final CRLFLineReader reader = new CRLFLineReader(new InputStreamReader(response.getBody().stream(), StandardCharsets.UTF_8)); - try { - for (String line; (line = reader.readLine()) != null && !disconnected; ) { - if (Thread.currentThread().isInterrupted()) { - break; - } - if (!connected) { - onConnected(); - connected = true; - } - if (TextUtils.isEmpty(line)) continue; - FanfouStreamObject object = JsonSerializer.parse(line, FanfouStreamObject.class); - if (!handleEvent(object, line)) { - onUnhandledEvent(object.getEvent(), line); - } - } - } catch (IOException e) { - onException(e); - } finally { - reader.close(); - } - } - - @Override - public final void error(@NonNull final MicroBlogException cause) { - onException(cause); - } - - public final void disconnect() { - disconnected = true; - } - - private boolean handleEvent(final FanfouStreamObject object, final String json) throws IOException { - switch (object.getEvent()) { - case "message.create": { - return onStatusCreation(object.getCreatedAt(), object.getSource(), - object.getTarget(), object.getObject(Status.class)); - } - } - return false; - } - - protected abstract boolean onConnected(); - - protected abstract boolean onDisconnect(int code, String reason); - - protected abstract boolean onException(@NonNull Throwable ex); - - protected abstract boolean onStatusCreation(@NonNull Date createdAt, @NonNull User source, - @Nullable User target, @NonNull Status object); - - protected abstract void onUnhandledEvent(@NonNull String event, @NonNull String json) - throws IOException; -} diff --git a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/fanfou/callback/SimpleFanfouUserStreamCallback.java b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/fanfou/callback/SimpleFanfouUserStreamCallback.java deleted file mode 100644 index 8a0a9c00d1..0000000000 --- a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/fanfou/callback/SimpleFanfouUserStreamCallback.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.fanfou.callback; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.mariotaku.microblog.library.twitter.model.Status; -import org.mariotaku.microblog.library.twitter.model.User; - -import java.io.IOException; -import java.util.Date; - -/** - * Created by mariotaku on 2017/3/11. - */ - -public abstract class SimpleFanfouUserStreamCallback extends FanfouUserStreamCallback { - @Override - protected boolean onConnected() { - return false; - } - - @Override - protected boolean onDisconnect(final int code, final String reason) { - return false; - } - - @Override - protected boolean onException(@NonNull final Throwable ex) { - return false; - } - - @Override - protected boolean onStatusCreation(@NonNull final Date createdAt, @NonNull final User source, - @Nullable final User target, @NonNull final Status status) { - return false; - } - - @Override - protected void onUnhandledEvent(@NonNull final String event, @NonNull final String json) - throws IOException { - - } -} diff --git a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/fanfou/model/FanfouStreamObject.java b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/fanfou/model/FanfouStreamObject.java deleted file mode 100644 index 84635a99b3..0000000000 --- a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/fanfou/model/FanfouStreamObject.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.fanfou.model; - -import androidx.annotation.NonNull; - -import com.bluelinelabs.logansquare.annotation.JsonField; -import com.bluelinelabs.logansquare.annotation.JsonObject; - -import org.mariotaku.commons.logansquare.JsonStringConverter; -import org.mariotaku.microblog.library.fanfou.model.util.StreamDateConverter; -import org.mariotaku.microblog.library.twitter.model.User; -import org.mariotaku.twidere.util.JsonSerializer; - -import java.io.IOException; -import java.util.Date; - -/** - * Created by mariotaku on 2017/3/11. - */ -@JsonObject -public class FanfouStreamObject { - @JsonField(name = "event") - String event; - @JsonField(name = "created_at", typeConverter = StreamDateConverter.class) - Date createdAt; - - @JsonField(name = "source") - User source; - @JsonField(name = "target") - User target; - @JsonField(name = "object", typeConverter = JsonStringConverter.class) - String rawObject; - - @NonNull - public String getEvent() { - if (event == null) return ""; - return event; - } - - public Date getCreatedAt() { - return createdAt; - } - - public User getSource() { - return source; - } - - public User getTarget() { - return target; - } - - public T getObject(Class cls) throws IOException { - if (rawObject == null) return null; - return JsonSerializer.parse(rawObject, cls); - } - -} diff --git a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/mastodon/MastodonStreaming.java b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/mastodon/MastodonStreaming.java deleted file mode 100644 index 57ea8d6687..0000000000 --- a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/mastodon/MastodonStreaming.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.mastodon; - -import org.mariotaku.microblog.library.MicroBlogException; -import org.mariotaku.microblog.library.mastodon.callback.MastodonUserStreamCallback; -import org.mariotaku.restfu.annotation.method.GET; - -/** - * Created by mariotaku on 2017/4/17. - */ - -public interface MastodonStreaming { - @GET("/v1/streaming/public") - void getUserStream(MastodonUserStreamCallback callback) throws MicroBlogException; -} diff --git a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/mastodon/callback/MastodonUserStreamCallback.java b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/mastodon/callback/MastodonUserStreamCallback.java deleted file mode 100644 index acd66e01e0..0000000000 --- a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/mastodon/callback/MastodonUserStreamCallback.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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.mastodon.callback; - -import androidx.annotation.NonNull; -import android.text.TextUtils; - -import org.mariotaku.microblog.library.MicroBlogException; -import org.mariotaku.microblog.library.mastodon.model.Notification; -import org.mariotaku.microblog.library.twitter.model.Status; -import org.mariotaku.microblog.library.util.CRLFLineReader; -import org.mariotaku.restfu.callback.RawCallback; -import org.mariotaku.restfu.http.HttpResponse; -import org.mariotaku.twidere.util.JsonSerializer; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; - -/** - * Created by mariotaku on 15/5/26. - */ -@SuppressWarnings({"WeakerAccess"}) -public abstract class MastodonUserStreamCallback implements RawCallback { - - private boolean connected; - - private boolean disconnected; - - @Override - public final void result(@NonNull final HttpResponse response) throws MicroBlogException, IOException { - if (!response.isSuccessful()) { - final MicroBlogException cause = new MicroBlogException(); - cause.setHttpResponse(response); - onException(cause); - return; - } - final CRLFLineReader reader = new CRLFLineReader(new InputStreamReader(response.getBody().stream(), StandardCharsets.UTF_8)); - try { - String event = null; - for (String line; (line = reader.readLine()) != null && !disconnected; ) { - if (Thread.currentThread().isInterrupted()) { - break; - } - if (!connected) { - onConnected(); - connected = true; - } - int valueIndex = line.indexOf(":"); - if (TextUtils.isEmpty(line) || valueIndex <= 0) { - event = null; - continue; - } - String name = line.substring(0, valueIndex); - valueIndex++; - while (line.charAt(valueIndex) == ' ') { - valueIndex++; - } - String value = line.substring(valueIndex); - switch (name) { - case "event": { - event = value; - break; - } - case "data": { - if (event != null) { - if (!handleEvent(event, value)) { - onUnhandledEvent(event, value); - } - } - event = null; - break; - } - default: { - event = null; - break; - } - } - } - } catch (IOException e) { - onException(e); - } finally { - reader.close(); - } - } - - @Override - public final void error(@NonNull final MicroBlogException cause) { - onException(cause); - } - - public final void disconnect() { - disconnected = true; - } - - private boolean handleEvent(final String event, final String payload) throws IOException { - switch (event) { - case "update": { - return onUpdate(JsonSerializer.parse(payload, Status.class)); - } - case "notification": { - return onNotification(JsonSerializer.parse(payload, Notification.class)); - } - case "delete": { - return onDelete(payload); - } - } - return false; - } - - protected abstract boolean onConnected(); - - protected abstract boolean onException(@NonNull Throwable ex); - - protected abstract boolean onUpdate(@NonNull Status status); - - protected abstract boolean onNotification(@NonNull Notification notification); - - protected abstract boolean onDelete(@NonNull String id); - - protected abstract void onUnhandledEvent(@NonNull String event, @NonNull String payload) - throws IOException; -} diff --git a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/TwitterUserStream.java b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/TwitterUserStream.java deleted file mode 100644 index 4c5166bc9c..0000000000 --- a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/TwitterUserStream.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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; - -import org.mariotaku.microblog.library.twitter.annotation.StreamWith; -import org.mariotaku.microblog.library.twitter.callback.UserStreamCallback; -import org.mariotaku.microblog.library.twitter.template.StatusAnnotationTemplate; -import org.mariotaku.restfu.annotation.method.GET; -import org.mariotaku.restfu.annotation.param.Params; - -/** - * Twitter UserStream API - * Created by mariotaku on 15/5/26. - */ -@Params(template = StatusAnnotationTemplate.class) -public interface TwitterUserStream { - - @GET("/user.json") - void getUserStream(@StreamWith String with, UserStreamCallback callback); - -} diff --git a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/callback/SimpleUserStreamCallback.java b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/callback/SimpleUserStreamCallback.java deleted file mode 100644 index 3f6d694b34..0000000000 --- a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/callback/SimpleUserStreamCallback.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * 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.callback; - -import androidx.annotation.NonNull; - -import org.mariotaku.microblog.library.twitter.model.DeletionEvent; -import org.mariotaku.microblog.library.twitter.model.DirectMessage; -import org.mariotaku.microblog.library.twitter.model.Status; -import org.mariotaku.microblog.library.twitter.model.TwitterStreamObject; -import org.mariotaku.microblog.library.twitter.model.User; -import org.mariotaku.microblog.library.twitter.model.UserList; -import org.mariotaku.microblog.library.twitter.model.Warning; - -import java.io.IOException; -import java.util.Date; - -/** - * Created by mariotaku on 2017/3/11. - */ - -public abstract class SimpleUserStreamCallback extends UserStreamCallback { - @Override - protected boolean onConnected() { - return false; - } - - @Override - protected boolean onDisconnectNotice(final int code, final String reason) { - return false; - } - - @Override - protected boolean onException(@NonNull final Throwable ex) { - return false; - } - - @Override - protected boolean onStatus(@NonNull final Status status) { - return false; - } - - @Override - protected boolean onDirectMessage(@NonNull final DirectMessage directMessage) { - return false; - } - - @Override - protected boolean onBlock(final Date createdAt, final User source, final User blockedUser) { - return false; - } - - @Override - protected boolean onDirectMessageDeleted(@NonNull final DeletionEvent event) { - return false; - } - - @Override - protected boolean onStatusDeleted(@NonNull final DeletionEvent event) { - return false; - } - - @Override - protected boolean onFavorite(@NonNull final Date createdAt, @NonNull final User source, @NonNull final User target, @NonNull final Status targetObject) { - return false; - } - - @Override - protected boolean onFollow(@NonNull final Date createdAt, @NonNull final User source, @NonNull final User target) { - return false; - } - - @Override - protected boolean onUnfollow(@NonNull final Date createdAt, @NonNull final User source, @NonNull final User target) { - return false; - } - - @Override - protected boolean onFriendList(@NonNull final String[] friendIds) { - return false; - } - - @Override - protected boolean onScrubGeo(final String userId, final String upToStatusId) { - return false; - } - - @Override - protected boolean onStallWarning(final Warning warn) { - return false; - } - - @Override - protected boolean onTrackLimitationNotice(final int numberOfLimitedStatuses) { - return false; - } - - @Override - protected boolean onUnblock(@NonNull final Date createdAt, @NonNull final User source, @NonNull final User unblockedUser) { - return false; - } - - @Override - protected boolean onUnfavorite(@NonNull final User source, @NonNull final User target, @NonNull final Status targetStatus) { - return false; - } - - @Override - protected boolean onUserListCreation(@NonNull final Date createdAt, @NonNull final User source, @NonNull final UserList targetObject) { - return false; - } - - @Override - protected boolean onUserListDeletion(@NonNull final Date createdAt, @NonNull final User source, @NonNull final UserList targetObject) { - return false; - } - - @Override - protected boolean onUserListMemberAddition(@NonNull final Date createdAt, @NonNull final User source, @NonNull final User target, @NonNull final UserList targetObject) { - return false; - } - - @Override - protected boolean onUserListMemberDeletion(@NonNull final Date createdAt, @NonNull final User source, @NonNull final User target, @NonNull final UserList targetObject) { - return false; - } - - @Override - protected boolean onUserListSubscription(@NonNull final Date createdAt, @NonNull final User source, @NonNull final User target, @NonNull final UserList targetObject) { - return false; - } - - @Override - protected boolean onUserListUnsubscription(@NonNull final Date createdAt, @NonNull final User source, @NonNull final User target, @NonNull final UserList targetObject) { - return false; - } - - @Override - protected boolean onUserListUpdate(@NonNull final Date createdAt, @NonNull final User source, @NonNull final UserList targetObject) { - return false; - } - - @Override - protected boolean onUserProfileUpdate(@NonNull final Date createdAt, @NonNull final User updatedUser) { - return false; - } - - @Override - protected boolean onQuotedTweet(@NonNull final Date createdAt, @NonNull final User source, @NonNull final User target, @NonNull final Status targetObject) { - return false; - } - - @Override - protected boolean onFavoritedRetweet(@NonNull final Date createdAt, @NonNull final User source, @NonNull final User target, @NonNull final Status targetObject) { - return false; - } - - @Override - protected boolean onRetweetedRetweet(@NonNull final Date createdAt, @NonNull final User source, @NonNull final User target, @NonNull final Status targetObject) { - return false; - } - - @Override - protected void onUnhandledEvent(@NonNull final TwitterStreamObject obj, @NonNull final String json) throws IOException { - - } -} diff --git a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/callback/UserStreamCallback.java b/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/callback/UserStreamCallback.java deleted file mode 100644 index 549ccb713e..0000000000 --- a/twidere.component.common/src/main/java/org/mariotaku/microblog/library/twitter/callback/UserStreamCallback.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * 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.callback; - -import androidx.annotation.NonNull; -import android.text.TextUtils; - -import org.mariotaku.microblog.library.MicroBlogException; -import org.mariotaku.microblog.library.twitter.model.DeletionEvent; -import org.mariotaku.microblog.library.twitter.model.DirectMessage; -import org.mariotaku.microblog.library.twitter.model.Status; -import org.mariotaku.microblog.library.twitter.model.StatusTargetObjectEvent; -import org.mariotaku.microblog.library.twitter.model.StreamEvent; -import org.mariotaku.microblog.library.twitter.model.TwitterStreamObject; -import org.mariotaku.microblog.library.twitter.model.TwitterStreamObject.Type; -import org.mariotaku.microblog.library.twitter.model.User; -import org.mariotaku.microblog.library.twitter.model.UserList; -import org.mariotaku.microblog.library.twitter.model.UserListTargetObjectEvent; -import org.mariotaku.microblog.library.twitter.model.Warning; -import org.mariotaku.microblog.library.util.CRLFLineReader; -import org.mariotaku.restfu.callback.RawCallback; -import org.mariotaku.restfu.http.HttpResponse; -import org.mariotaku.twidere.util.JsonSerializer; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.Date; - -/** - * Created by mariotaku on 15/5/26. - */ -@SuppressWarnings({"WeakerAccess"}) -public abstract class UserStreamCallback implements RawCallback { - - private boolean connected; - - private boolean disconnected; - - @Override - public final void result(@NonNull final HttpResponse response) throws MicroBlogException, IOException { - if (!response.isSuccessful()) { - final MicroBlogException cause = new MicroBlogException(); - cause.setHttpResponse(response); - onException(cause); - return; - } - final CRLFLineReader reader = new CRLFLineReader(new InputStreamReader(response.getBody().stream(), StandardCharsets.UTF_8)); - try { - for (String line; (line = reader.readLine()) != null && !disconnected; ) { - if (Thread.currentThread().isInterrupted()) { - break; - } - if (!connected) { - onConnected(); - connected = true; - } - if (TextUtils.isEmpty(line)) continue; - final TwitterStreamObject object = JsonSerializer.parse(line, TwitterStreamObject.class); - if (!handleEvent(object, line)) { - onUnhandledEvent(object, line); - } - } - } catch (IOException e) { - onException(e); - } finally { - reader.close(); - } - } - - @Override - public final void error(@NonNull final MicroBlogException cause) { - onException(cause); - } - - public final void disconnect() { - disconnected = true; - } - - private boolean handleEvent(final TwitterStreamObject object, final String json) throws IOException { - switch (object.determine()) { - case Type.FRIENDS: { - return onFriendList(object.getFriends()); - } - case Type.STATUS: { - return onStatus(JsonSerializer.parse(json, Status.class)); - } - case Type.DIRECT_MESSAGE: { - return onDirectMessage(object.getDirectMessage()); - } - case Type.DELETE: { - final TwitterStreamObject.Delete delete = object.getDelete(); - if (delete.getStatus() != null) { - return onStatusDeleted(delete.getStatus()); - } else if (delete.getDirectMessage() != null) { - return onDirectMessageDeleted(delete.getDirectMessage()); - } - break; - } - case Type.LIMIT: { - return onTrackLimitationNotice(object.getLimit().getTrack()); - } - case Type.STALL_WARNING: { - return onStallWarning(object.getWarning()); - } - case Type.SCRUB_GEO: { - TwitterStreamObject.ScrubGeo scrubGeo = object.getScrubGeo(); - return onScrubGeo(scrubGeo.getUserId(), scrubGeo.getUpToStatusId()); - } - case Type.FAVORITE: { - StatusTargetObjectEvent event = JsonSerializer.parse(json, StatusTargetObjectEvent.class); - return onFavorite(event.getCreatedAt(), event.getSource(), event.getTarget(), - event.getTargetObject()); - } - case Type.UNFAVORITE: { - StatusTargetObjectEvent event = JsonSerializer.parse(json, StatusTargetObjectEvent.class); - return onUnfavorite(event.getSource(), event.getTarget(), event.getTargetObject()); - } - case Type.QUOTED_TWEET: { - StatusTargetObjectEvent event = JsonSerializer.parse(json, StatusTargetObjectEvent.class); - return onQuotedTweet(event.getCreatedAt(), event.getSource(), event.getTarget(), - event.getTargetObject()); - } - case Type.RETWEETED_RETWEET: { - StatusTargetObjectEvent event = JsonSerializer.parse(json, StatusTargetObjectEvent.class); - return onRetweetedRetweet(event.getCreatedAt(), event.getSource(), event.getTarget(), - event.getTargetObject()); - } - case Type.FAVORITED_RETWEET: { - StatusTargetObjectEvent event = JsonSerializer.parse(json, StatusTargetObjectEvent.class); - return onFavoritedRetweet(event.getCreatedAt(), event.getSource(), event.getTarget(), - event.getTargetObject()); - } - case Type.FOLLOW: { - StreamEvent event = JsonSerializer.parse(json, StreamEvent.class); - return onFollow(event.getCreatedAt(), event.getSource(), event.getTarget()); - } - case Type.UNFOLLOW: { - StreamEvent event = JsonSerializer.parse(json, StreamEvent.class); - return onUnfollow(event.getCreatedAt(), event.getSource(), event.getTarget()); - } - case Type.USER_LIST_MEMBER_ADDED: { - UserListTargetObjectEvent event = JsonSerializer.parse(json, UserListTargetObjectEvent.class); - return onUserListMemberAddition(event.getCreatedAt(), event.getSource(), - event.getTarget(), event.getTargetObject()); - } - case Type.USER_LIST_MEMBER_DELETED: { - UserListTargetObjectEvent event = JsonSerializer.parse(json, UserListTargetObjectEvent.class); - return onUserListMemberDeletion(event.getCreatedAt(), event.getSource(), - event.getTarget(), event.getTargetObject()); - } - case Type.USER_LIST_SUBSCRIBED: { - UserListTargetObjectEvent event = JsonSerializer.parse(json, UserListTargetObjectEvent.class); - return onUserListSubscription(event.getCreatedAt(), event.getSource(), - event.getTarget(), event.getTargetObject()); - } - case Type.USER_LIST_UNSUBSCRIBED: { - UserListTargetObjectEvent event = JsonSerializer.parse(json, UserListTargetObjectEvent.class); - return onUserListUnsubscription(event.getCreatedAt(), event.getSource(), - event.getTarget(), event.getTargetObject()); - } - case Type.USER_LIST_CREATED: { - UserListTargetObjectEvent event = JsonSerializer.parse(json, UserListTargetObjectEvent.class); - return onUserListCreation(event.getCreatedAt(), event.getSource(), - event.getTargetObject()); - } - case Type.USER_LIST_UPDATED: { - UserListTargetObjectEvent event = JsonSerializer.parse(json, UserListTargetObjectEvent.class); - return onUserListUpdate(event.getCreatedAt(), event.getSource(), - event.getTargetObject()); - } - case Type.USER_LIST_DESTROYED: { - UserListTargetObjectEvent event = JsonSerializer.parse(json, UserListTargetObjectEvent.class); - return onUserListDeletion(event.getCreatedAt(), event.getSource(), - event.getTargetObject()); - } - case Type.USER_UPDATE: { - StreamEvent event = JsonSerializer.parse(json, StreamEvent.class); - return onUserProfileUpdate(event.getCreatedAt(), event.getSource()); - } - case Type.BLOCK: { - StreamEvent event = JsonSerializer.parse(json, StreamEvent.class); - return onBlock(event.getCreatedAt(), event.getSource(), event.getTarget()); - } - case Type.UNBLOCK: { - StreamEvent event = JsonSerializer.parse(json, StreamEvent.class); - return onUnblock(event.getCreatedAt(), event.getSource(), event.getTarget()); - } - case Type.DISCONNECTION: - TwitterStreamObject.Disconnect disconnect = object.getDisconnect(); - return onDisconnectNotice(disconnect.getCode(), disconnect.getReason()); - } - return false; - } - - protected abstract boolean onConnected(); - - protected abstract boolean onDisconnectNotice(int code, String reason); - - protected abstract boolean onException(@NonNull Throwable ex); - - protected abstract boolean onStatus(@NonNull Status status); - - protected abstract boolean onDirectMessage(@NonNull DirectMessage directMessage); - - protected abstract boolean onBlock(Date createdAt, User source, User blockedUser); - - protected abstract boolean onDirectMessageDeleted(@NonNull DeletionEvent event); - - protected abstract boolean onStatusDeleted(@NonNull DeletionEvent event); - - protected abstract boolean onFavorite(@NonNull Date createdAt, @NonNull User source, - @NonNull User target, @NonNull Status targetObject); - - protected abstract boolean onFollow(@NonNull Date createdAt, @NonNull User source, - @NonNull User target); - - protected abstract boolean onUnfollow(@NonNull Date createdAt, @NonNull User source, - @NonNull User target); - - protected abstract boolean onFriendList(@NonNull String[] friendIds); - - protected abstract boolean onScrubGeo(String userId, String upToStatusId); - - protected abstract boolean onStallWarning(Warning warn); - - protected abstract boolean onTrackLimitationNotice(int numberOfLimitedStatuses); - - protected abstract boolean onUnblock(@NonNull Date createdAt, @NonNull User source, - @NonNull User unblockedUser); - - protected abstract boolean onUnfavorite(@NonNull User source, @NonNull User target, - @NonNull Status targetStatus); - - protected abstract boolean onUserListCreation(@NonNull Date createdAt, @NonNull User source, - @NonNull UserList targetObject); - - protected abstract boolean onUserListDeletion(@NonNull Date createdAt, @NonNull User source, - @NonNull UserList targetObject); - - protected abstract boolean onUserListMemberAddition(@NonNull Date createdAt, @NonNull User source, - @NonNull User target, @NonNull UserList targetObject); - - protected abstract boolean onUserListMemberDeletion(@NonNull Date createdAt, @NonNull User source, - @NonNull User target, @NonNull UserList targetObject); - - protected abstract boolean onUserListSubscription(@NonNull Date createdAt, @NonNull User source, - @NonNull User target, @NonNull UserList targetObject); - - protected abstract boolean onUserListUnsubscription(@NonNull Date createdAt, @NonNull User source, - @NonNull User target, @NonNull UserList targetObject); - - protected abstract boolean onUserListUpdate(@NonNull Date createdAt, @NonNull User source, - @NonNull UserList targetObject); - - protected abstract boolean onUserProfileUpdate(@NonNull Date createdAt, - @NonNull User updatedUser); - - protected abstract boolean onQuotedTweet(@NonNull Date createdAt, @NonNull User source, - @NonNull User target, @NonNull Status targetObject); - - protected abstract boolean onFavoritedRetweet(@NonNull Date createdAt, @NonNull User source, - @NonNull User target, @NonNull Status targetObject); - - protected abstract boolean onRetweetedRetweet(@NonNull Date createdAt, @NonNull User source, - @NonNull User target, @NonNull Status targetObject); - - protected abstract void onUnhandledEvent(@NonNull TwitterStreamObject obj, @NonNull String json) - throws IOException; -} diff --git a/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java b/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java index 34c6c95c75..96c86b0c03 100644 --- a/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java +++ b/twidere.component.common/src/main/java/org/mariotaku/twidere/constant/SharedPreferenceConstants.java @@ -156,8 +156,6 @@ public interface SharedPreferenceConstants { String KEY_MENTIONS_NOTIFICATION = "mentions_notification"; @ExportablePreference(BOOLEAN) String KEY_DIRECT_MESSAGES_NOTIFICATION = "direct_messages_notification"; - @ExportablePreference(BOOLEAN) - String KEY_ENABLE_STREAMING = "enable_streaming"; @ExportablePreference(STRING) String KEY_NOTIFICATION_RINGTONE = "notification_ringtone"; @ExportablePreference(INT) @@ -276,12 +274,6 @@ public interface SharedPreferenceConstants { String KEY_FLOATING_DETAILED_CONTENTS = "floating_detailed_contents"; @ExportablePreference(STRING) String KEY_MULTI_COLUMN_TAB_WIDTH = "multi_column_tab_width"; - @ExportablePreference(BOOLEAN) - String KEY_STREAMING_ENABLED = "streaming_enabled"; - @ExportablePreference(BOOLEAN) - String KEY_STREAMING_NON_METERED_NETWORK = "streaming_non_metered_network"; - @ExportablePreference(BOOLEAN) - String KEY_STREAMING_POWER_SAVING = "streaming_power_saving"; @ExportablePreference(STRING) String KEY_NAVBAR_STYLE = "navbar_style"; @ExportablePreference(STRING) diff --git a/twidere/src/debug/java/org/mariotaku/twidere/util/DebugModeUtils.java b/twidere/src/debug/java/org/mariotaku/twidere/util/DebugModeUtils.java index 8c20de5a39..f620d908a5 100644 --- a/twidere/src/debug/java/org/mariotaku/twidere/util/DebugModeUtils.java +++ b/twidere/src/debug/java/org/mariotaku/twidere/util/DebugModeUtils.java @@ -27,10 +27,8 @@ import com.facebook.stetho.okhttp3.StethoInterceptor; import org.mariotaku.stethoext.bsh.BshRuntimeReplFactoryBuilder; -import org.mariotaku.twidere.BuildConfig; import org.mariotaku.twidere.util.net.NoIntercept; import org.mariotaku.twidere.util.stetho.AccountsDumperPlugin; -import org.mariotaku.twidere.util.stetho.UserStreamDumperPlugin; import okhttp3.OkHttpClient; @@ -57,14 +55,13 @@ public static void initForApplication(final Application application) { Stetho.initialize(Stetho.newInitializerBuilder(application) .enableDumpapp(() -> new Stetho.DefaultDumperPluginsBuilder(application) .provide(new AccountsDumperPlugin(application)) - .provide(new UserStreamDumperPlugin(application)) .finish()) .enableWebKitInspector(() -> new Stetho.DefaultInspectorModulesBuilder(application) .runtimeRepl(new BshRuntimeReplFactoryBuilder(application).build()) .finish()) .build()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { -// WebView.setWebContentsDebuggingEnabled(true); + WebView.setWebContentsDebuggingEnabled(true); } } } diff --git a/twidere/src/debug/kotlin/org/mariotaku/twidere/util/stetho/UserStreamDumperPlugin.kt b/twidere/src/debug/kotlin/org/mariotaku/twidere/util/stetho/UserStreamDumperPlugin.kt deleted file mode 100644 index 275dccffc4..0000000000 --- a/twidere/src/debug/kotlin/org/mariotaku/twidere/util/stetho/UserStreamDumperPlugin.kt +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2017 Mariotaku Lee - * - * 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 . - */ - -package org.mariotaku.twidere.util.stetho - -import android.accounts.AccountManager -import android.content.Context -import com.facebook.stetho.dumpapp.DumperContext -import com.facebook.stetho.dumpapp.DumperPlugin -import org.apache.commons.cli.GnuParser -import org.apache.commons.cli.HelpFormatter -import org.apache.commons.cli.Options -import org.mariotaku.ktextension.subArray -import org.mariotaku.microblog.library.fanfou.FanfouStream -import org.mariotaku.microblog.library.mastodon.MastodonStreaming -import org.mariotaku.microblog.library.mastodon.callback.MastodonUserStreamCallback -import org.mariotaku.microblog.library.mastodon.model.Notification -import org.mariotaku.microblog.library.twitter.TwitterUserStream -import org.mariotaku.microblog.library.twitter.annotation.StreamWith -import org.mariotaku.microblog.library.twitter.model.Activity -import org.mariotaku.microblog.library.twitter.model.DirectMessage -import org.mariotaku.microblog.library.twitter.model.Status -import org.mariotaku.twidere.annotation.AccountType -import org.mariotaku.twidere.extension.model.api.microblog.toParcelable -import org.mariotaku.twidere.extension.model.newMicroBlogInstance -import org.mariotaku.twidere.model.AccountDetails -import org.mariotaku.twidere.model.ActivityTitleSummaryMessage -import org.mariotaku.twidere.model.UserKey -import org.mariotaku.twidere.model.util.AccountUtils -import org.mariotaku.twidere.util.UserColorNameManager -import org.mariotaku.twidere.util.dagger.DependencyHolder -import org.mariotaku.twidere.util.streaming.FanfouTimelineStreamCallback -import org.mariotaku.twidere.util.streaming.TwitterTimelineStreamCallback - -/** - * Created by mariotaku on 2017/3/9. - */ -class UserStreamDumperPlugin(val context: Context) : DumperPlugin { - - private val syntax = "$name [-ti]" - - override fun dump(dumpContext: DumperContext) { - val parser = GnuParser() - val options = Options() - options.addOption("t", "timeline", false, "Include timeline") - options.addOption("i", "interactions", false, "Include interactions") - options.addOption("v", "verbose", false, "Print full object") - val argsList = dumpContext.argsAsList - val formatter = HelpFormatter() - if (argsList.isEmpty()) { - formatter.printHelp(dumpContext.stderr, syntax, options) - return - } - val cmdLine = parser.parse(options, argsList.subArray(1..argsList.lastIndex)) - val manager = DependencyHolder.get(context).userColorNameManager - val includeTimeline = cmdLine.hasOption("timeline") - val includeInteractions = cmdLine.hasOption("interactions") - val verboseMode = cmdLine.hasOption("verbose") - val accountKey = UserKey.valueOf(argsList[0]) - val am = AccountManager.get(context) - val account = AccountUtils.getAccountDetails(am, accountKey, true) ?: return - when (account.type) { - AccountType.TWITTER -> { - beginTwitterStream(account, dumpContext, includeInteractions, includeTimeline, - verboseMode, manager) - } - AccountType.FANFOU -> { - beginFanfouStream(account, dumpContext, includeInteractions, includeTimeline, - verboseMode, manager) - } - AccountType.MASTODON -> { - beginMastodonStream(account, dumpContext, includeInteractions, includeTimeline, - verboseMode, manager) - } - else -> { - dumpContext.stderr.println("Unsupported account type ${account.type}") - dumpContext.stderr.flush() - } - } - - } - - private fun beginMastodonStream(account: AccountDetails, dumpContext: DumperContext, - includeInteractions: Boolean, includeTimeline: Boolean, verboseMode: Boolean, - manager: UserColorNameManager) { - val streaming = account.newMicroBlogInstance(context, cls = MastodonStreaming::class.java) - dumpContext.stdout.println("Beginning user stream...") - dumpContext.stdout.flush() - val callback = object : MastodonUserStreamCallback() { - override fun onConnected(): Boolean { - return false - } - - override fun onException(ex: Throwable): Boolean { - ex.printStackTrace(dumpContext.stderr) - dumpContext.stderr.flush() - return true - } - - override fun onUpdate(status: Status): Boolean { - return false - } - - override fun onNotification(notification: Notification): Boolean { - return false - } - - override fun onDelete(id: String): Boolean { - return false - } - - override fun onUnhandledEvent(event: String, payload: String) { - dumpContext.stdout.println(payload) - dumpContext.stdout.flush() - } - - } - streaming.getUserStream(callback) - } - - private fun beginTwitterStream(account: AccountDetails, dumpContext: DumperContext, - includeInteractions: Boolean, includeTimeline: Boolean, verboseMode: Boolean, - manager: UserColorNameManager) { - val userStream = account.newMicroBlogInstance(context, cls = TwitterUserStream::class.java) - dumpContext.stdout.println("Beginning user stream...") - dumpContext.stdout.flush() - val callback = object : TwitterTimelineStreamCallback(account.key.id) { - override fun onException(ex: Throwable): Boolean { - ex.printStackTrace(dumpContext.stderr) - dumpContext.stderr.flush() - return true - } - - override fun onHomeTimeline(status: Status): Boolean { - if (!includeTimeline && includeInteractions) return true - if (verboseMode) { - dumpContext.stdout.println("Home: @${status.user.screenName}: ${status.toString().trim('\n')}") - } else { - dumpContext.stdout.println("Home: @${status.user.screenName}: ${status.text.trim('\n')}") - } - dumpContext.stdout.flush() - return true - } - - override fun onActivityAboutMe(activity: Activity): Boolean { - if (!includeInteractions && includeTimeline) return true - if (verboseMode) { - dumpContext.stdout.println("Activity: @${activity.toString().trim('\n')}") - } else { - val pActivity = activity.toParcelable(account) - val message = ActivityTitleSummaryMessage.get(context, manager, pActivity, - pActivity.sources_lite, 0, true, true) - if (message != null) { - dumpContext.stdout.println("Activity: ${message.title}: ${message.summary}") - } else { - dumpContext.stdout.println("Activity unsupported: ${activity.action}") - } - } - dumpContext.stdout.flush() - return true - } - - override fun onDirectMessage(directMessage: DirectMessage): Boolean { - if (verboseMode) { - dumpContext.stdout.println("Message: @${directMessage.senderScreenName}: ${directMessage.toString().trim('\n')}") - } else { - dumpContext.stdout.println("Message: @${directMessage.senderScreenName}: ${directMessage.text.trim('\n')}") - } - dumpContext.stdout.flush() - return true - } - } - try { - userStream.getUserStream(StreamWith.USER, callback) - } catch (e: Exception) { - e.printStackTrace(dumpContext.stderr) - } - } - - private fun beginFanfouStream(account: AccountDetails, dumpContext: DumperContext, - includeInteractions: Boolean, includeTimeline: Boolean, verboseMode: Boolean, - manager: UserColorNameManager) { - val userStream = account.newMicroBlogInstance(context, cls = FanfouStream::class.java) - dumpContext.stdout.println("Beginning user stream...") - dumpContext.stdout.flush() - if (includeTimeline) { - dumpContext.stderr.println("Timeline only is effectively useless for Fanfou") - dumpContext.stderr.flush() - } - val callback = object : FanfouTimelineStreamCallback(account.key.id) { - - override fun onException(ex: Throwable): Boolean { - ex.printStackTrace(dumpContext.stderr) - dumpContext.stderr.flush() - return true - } - - override fun onHomeTimeline(status: Status): Boolean { - return false - } - - override fun onActivityAboutMe(activity: Activity): Boolean { - if (!includeInteractions && includeTimeline) return true - val pActivity = activity.toParcelable(account) - val message = ActivityTitleSummaryMessage.get(context, manager, pActivity, - pActivity.sources_lite, 0, true, true) - if (message != null) { - dumpContext.stdout.println("Activity: ${message.title}: ${message.summary}") - } else { - dumpContext.stdout.println("Activity unsupported: ${activity.action}") - } - dumpContext.stdout.flush() - return true - } - - override fun onUnhandledEvent(event: String, json: String) { - dumpContext.stdout.println("Unhandled: $event: $json") - dumpContext.stdout.flush() - } - } - try { - userStream.getUserStream(callback) - } catch (e: Exception) { - e.printStackTrace(dumpContext.stderr) - } - } - - override fun getName() = "userstream" - -} \ No newline at end of file diff --git a/twidere/src/main/AndroidManifest.xml b/twidere/src/main/AndroidManifest.xml index 1d6a171d41..9f717cd89b 100644 --- a/twidere/src/main/AndroidManifest.xml +++ b/twidere/src/main/AndroidManifest.xml @@ -622,9 +622,6 @@ android:exported="true" android:label="@string/label_refresh_and_sync_service" android:permission="android.permission.BIND_JOB_SERVICE"/> - @@ -711,12 +708,6 @@ android:resource="@xml/pickncrop__file_paths"/> - - - - - - diff --git a/twidere/src/main/images/drawable-mdpi/ic_action_streaming.svg b/twidere/src/main/images/drawable-mdpi/ic_action_streaming.svg deleted file mode 100644 index 85a2f98bc2..0000000000 --- a/twidere/src/main/images/drawable-mdpi/ic_action_streaming.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - ic_action_streaming-mdpi - Created with Sketch. - - - - - - - - - - \ No newline at end of file diff --git a/twidere/src/main/images/drawable-mdpi/ic_stat_streaming.svg b/twidere/src/main/images/drawable-mdpi/ic_stat_streaming.svg deleted file mode 100644 index 92ec1ab807..0000000000 --- a/twidere/src/main/images/drawable-mdpi/ic_stat_streaming.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - ic_stat_streaming-mdpi - Created with Sketch. - - - - - - - - - - \ No newline at end of file diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt index a8382cfa96..896422922d 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/HomeActivity.kt @@ -103,7 +103,6 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Activities import org.mariotaku.twidere.provider.TwidereDataStore.Messages.Conversations import org.mariotaku.twidere.provider.TwidereDataStore.Statuses import org.mariotaku.twidere.receiver.NotificationReceiver -import org.mariotaku.twidere.service.StreamingService import org.mariotaku.twidere.util.* import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback import org.mariotaku.twidere.util.premium.ExtraFeaturesService @@ -288,8 +287,6 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp val initialTabPosition = handleIntent(intent, savedInstanceState == null) setTabPosition(initialTabPosition) - StreamingService.startOrStopService(this) - if (!showDrawerTutorial() && !kPreferences[defaultAutoRefreshAskedKey]) { showAutoRefreshConfirm() } @@ -329,9 +326,6 @@ class HomeActivity : BaseActivity(), OnClickListener, OnPageChangeListener, Supp override fun onDestroy() { if (isFinishing) { - // Stop only when exiting explicitly - StreamingService.startOrStopService(this) - // Delete unused items in databases. val context = applicationContext task { DataStoreUtils.cleanDatabasesByItemLimit(context) } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt index 96bfc7e440..7216b56a16 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/SettingsActivity.kt @@ -215,8 +215,6 @@ class SettingsActivity : BaseActivity(), OnItemClickListener, OnPreferenceStartF ExtensionsListFragment::class.java) entriesAdapter.addPreference("refresh", R.drawable.ic_action_refresh, getString(R.string.action_refresh), R.xml.preferences_refresh) - entriesAdapter.addPreference("streaming", R.drawable.ic_action_streaming, getString(R.string.settings_streaming), - R.xml.preferences_streaming) entriesAdapter.addPreference("notifications", R.drawable.ic_action_notification, getString(R.string.settings_notifications), R.xml.preferences_notifications) entriesAdapter.addPreference("network", R.drawable.ic_action_web, getString(R.string.network), diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/app/TwidereApplication.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/app/TwidereApplication.kt index 5e70fbdbd7..490ccd1c95 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/app/TwidereApplication.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/app/TwidereApplication.kt @@ -58,7 +58,6 @@ import org.mariotaku.twidere.extension.model.save import org.mariotaku.twidere.extension.setLocale import org.mariotaku.twidere.model.DefaultFeatures import org.mariotaku.twidere.receiver.ConnectivityStateReceiver -import org.mariotaku.twidere.service.StreamingService import org.mariotaku.twidere.util.* import org.mariotaku.twidere.util.concurrent.ConstantFuture import org.mariotaku.twidere.util.content.TwidereSQLiteOpenHelper @@ -220,15 +219,6 @@ class TwidereApplication : Application(), OnSharedPreferenceChangeListener { KEY_NAME_FIRST, KEY_I_WANT_MY_STARS_BACK -> { contentNotificationManager.updatePreferences() } - streamingEnabledKey.key, streamingPowerSavingKey.key, - streamingNonMeteredNetworkKey.key -> { - val streamingIntent = Intent(this, StreamingService::class.java) - if (activityTracker.isHomeActivityLaunched) { - startService(streamingIntent) - } else { - stopService(streamingIntent) - } - } KEY_OVERRIDE_LANGUAGE -> { applyLanguageSettings() } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/constant/PreferenceKeys.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/constant/PreferenceKeys.kt index 0dff555cdf..113653c945 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/constant/PreferenceKeys.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/constant/PreferenceKeys.kt @@ -74,9 +74,6 @@ val floatingDetailedContentsKey = KBooleanKey(KEY_FLOATING_DETAILED_CONTENTS, tr val localTrendsWoeIdKey = KIntKey(KEY_LOCAL_TRENDS_WOEID, 1) val phishingLinksWaringKey = KBooleanKey(KEY_PHISHING_LINK_WARNING, true) val multiColumnWidthKey = KStringKey(KEY_MULTI_COLUMN_TAB_WIDTH, "normal") -val streamingEnabledKey = KBooleanKey(KEY_STREAMING_ENABLED, false) -val streamingNonMeteredNetworkKey = KBooleanKey(KEY_STREAMING_NON_METERED_NETWORK, true) -val streamingPowerSavingKey = KBooleanKey(KEY_STREAMING_POWER_SAVING, true) val quickSendKey = KBooleanKey(KEY_QUICK_SEND, false) val refreshAfterTweetKey = KBooleanKey(KEY_REFRESH_AFTER_TWEET, false) val refreshOnStartKey = KBooleanKey(KEY_REFRESH_ON_START, false) 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 0739981377..d7e20320cb 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 @@ -124,7 +124,3 @@ val Array.textLimit: Int } return limit } - - -val AccountDetails.isStreamingSupported: Boolean - get() = type == AccountType.TWITTER \ No newline at end of file diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/CredentialsExtensions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/CredentialsExtensions.kt index 3a4b864bed..e73fbeb1aa 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/CredentialsExtensions.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/model/CredentialsExtensions.kt @@ -5,10 +5,8 @@ import android.net.Uri import android.text.TextUtils import org.mariotaku.microblog.library.MicroBlog import org.mariotaku.microblog.library.MicroBlogException -import org.mariotaku.microblog.library.fanfou.FanfouStream import org.mariotaku.microblog.library.mastodon.Mastodon import org.mariotaku.microblog.library.mastodon.MastodonOAuth2 -import org.mariotaku.microblog.library.mastodon.MastodonStreaming import org.mariotaku.microblog.library.twitter.* import org.mariotaku.microblog.library.twitter.auth.BasicAuthorization import org.mariotaku.microblog.library.twitter.auth.EmptyAuthorization @@ -95,18 +93,10 @@ fun Credentials.getEndpoint(cls: Class<*>): Endpoint { domain = "api" versionSuffix = null } - TwitterUserStream::class.java.isAssignableFrom(cls) -> { - domain = "userstream" - versionSuffix = if (noVersionSuffix) null else "/1.1/" - } TwitterCaps::class.java.isAssignableFrom(cls) -> { domain = "caps" versionSuffix = null } - FanfouStream::class.java.isAssignableFrom(cls) -> { - domain = "stream" - versionSuffix = null - } TwitterWeb::class.java.isAssignableFrom(cls) -> { domain = null versionSuffix = null @@ -119,10 +109,6 @@ fun Credentials.getEndpoint(cls: Class<*>): Endpoint { domain = null versionSuffix = null } - MastodonStreaming::class.java.isAssignableFrom(cls) -> { - domain = null - versionSuffix = null - } else -> throw UnsupportedOperationException("Unsupported class $cls") } val endpointUrl = MicroBlogAPIFactory.getApiUrl(apiUrlFormat, domain, versionSuffix) @@ -165,14 +151,6 @@ fun newMicroBlogInstance(context: Context, endpoint: Endpoint, auth: Authori holder.connectionPool, holder.cache) factory.setHttpClient(uploadHttpClient) } - TwitterUserStream::class.java, FanfouStream::class.java, MastodonStreaming::class.java -> { - val conf = HttpClientFactory.HttpClientConfiguration(holder.preferences) - // Use longer read timeout for streaming - conf.readTimeoutSecs = 300 - val streamHttpClient = HttpClientFactory.createRestHttpClient(conf, holder.dns, - holder.connectionPool, holder.cache) - factory.setHttpClient(streamHttpClient) - } else -> { factory.setHttpClient(holder.restHttpClient) } @@ -185,9 +163,7 @@ fun newMicroBlogInstance(context: Context, endpoint: Endpoint, auth: Authori } AccountType.FANFOU -> { factory.setConstantPool(sFanfouConstantPool) - if (cls != FanfouStream::class.java) { - extraRequestParams = mapOf("format" to "html") - } + extraRequestParams = mapOf("format" to "html") } } factory.setRestConverterFactory(TwitterConverterFactory) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AccountStreamingSettingsFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AccountStreamingSettingsFragment.kt deleted file mode 100644 index b16408293d..0000000000 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/AccountStreamingSettingsFragment.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2017 Mariotaku Lee - * - * 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 . - */ - -package org.mariotaku.twidere.fragment - -import org.mariotaku.twidere.R -import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_ENABLE_STREAMING -import org.mariotaku.twidere.service.StreamingService - -class AccountStreamingSettingsFragment : BaseAccountPreferenceFragment() { - - override val preferencesResource: Int - get() = R.xml.preferences_account_streaming - - override val switchPreferenceDefault: Boolean = false - - override val switchPreferenceKey: String? = KEY_ENABLE_STREAMING - - override fun onSwitchPreferenceChanged(isChecked: Boolean) { - super.onSwitchPreferenceChanged(isChecked) - context?.let { StreamingService.startOrStopService(it) } - } -} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/UserFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/UserFragment.kt index 67ece98e42..e1108bda6c 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/UserFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/UserFragment.kt @@ -992,10 +992,6 @@ class UserFragment : BaseFragment(), OnClickListener, OnLinkClickListener, } R.id.enable_notifications -> { val newState = !item.isChecked - if (newState) { - Toast.makeText(context, R.string.message_toast_notification_enabled_hint, - Toast.LENGTH_SHORT).show() - } val update = FriendshipUpdate() update.deviceNotifications(newState) twitter.updateFriendship(accountKey, user.key, update) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/model/AccountPreferences.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/model/AccountPreferences.kt index 40566dd037..0d1e64632b 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/model/AccountPreferences.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/model/AccountPreferences.kt @@ -95,21 +95,6 @@ class AccountPreferences( val isAutoRefreshTrendsEnabled: Boolean get() = accountPreferences.getBoolean(KEY_AUTO_REFRESH_TRENDS, DEFAULT_AUTO_REFRESH_TRENDS) - val isStreamingEnabled: Boolean - get() = accountPreferences.getBoolean(KEY_ENABLE_STREAMING, false) - - val isStreamHomeTimelineEnabled: Boolean - get() = accountPreferences.getBoolean("stream_home_timeline", true) - - val isStreamInteractionsEnabled: Boolean - get() = accountPreferences.getBoolean("stream_interactions", true) - - val isStreamDirectMessagesEnabled: Boolean - get() = accountPreferences.getBoolean("stream_direct_messages", true) - - val isStreamNotificationUsersEnabled: Boolean - get() = accountPreferences.getBoolean("stream_notification_users", true) - val isDirectMessagesNotificationEnabled: Boolean get() = accountPreferences.getBoolean(KEY_DIRECT_MESSAGES_NOTIFICATION, DEFAULT_DIRECT_MESSAGES_NOTIFICATION) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/model/notification/NotificationChannelSpec.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/model/notification/NotificationChannelSpec.kt index eeaaf0b822..c6533eaca5 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/model/notification/NotificationChannelSpec.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/model/notification/NotificationChannelSpec.kt @@ -47,13 +47,6 @@ enum class NotificationChannelSpec( backgroundProgresses("background_progresses", R.string.notification_channel_name_background_progresses, importance = NotificationManager.IMPORTANCE_MIN), - /** - * For ongoing notifications indicating service statuses. - * Such as notification showing streaming service running - */ - serviceStatuses("service_statuses", R.string.notification_channel_name_service_statuses, - importance = NotificationManager.IMPORTANCE_MIN), - /** * For updates related to micro-blogging features. * Such as new statuses posted by friends. diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/model/tab/impl/InteractionsTabConfiguration.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/model/tab/impl/InteractionsTabConfiguration.kt index 050e5158c1..fe8c7a7a71 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/model/tab/impl/InteractionsTabConfiguration.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/model/tab/impl/InteractionsTabConfiguration.kt @@ -29,7 +29,6 @@ import org.mariotaku.twidere.annotation.AccountType import org.mariotaku.twidere.annotation.TabAccountFlags import org.mariotaku.twidere.constant.IntentConstants.EXTRA_MENTIONS_ONLY import org.mariotaku.twidere.constant.IntentConstants.EXTRA_MY_FOLLOWING_ONLY -import org.mariotaku.twidere.extension.model.isOfficial import org.mariotaku.twidere.fragment.InteractionsTimelineFragment import org.mariotaku.twidere.model.AccountDetails import org.mariotaku.twidere.model.Tab @@ -98,18 +97,15 @@ class InteractionsTabConfiguration : TabConfiguration() { val titleView: TextView = view.findViewById(android.R.id.title) val summaryView: TextView = view.findViewById(android.R.id.summary) - var requiresStreaming = false var interactionsAvailable = false if (account == null || account.dummy) { val am = AccountManager.get(context) val accounts = AccountUtils.getAllAccountDetails(am, false) interactionsAvailable = accounts.any { it.supportsInteractions } - requiresStreaming = accounts.all { it.requiresStreaming } } else when (account.type) { AccountType.TWITTER -> { interactionsAvailable = true - requiresStreaming = !account.isOfficial(context) } AccountType.MASTODON -> { interactionsAvailable = true @@ -122,12 +118,7 @@ class InteractionsTabConfiguration : TabConfiguration() { checkBox.isEnabled = interactionsAvailable if (interactionsAvailable) { checkBox.isChecked = valueBackup - if (requiresStreaming) { - summaryView.setText(R.string.summary_interactions_streaming_required) - summaryView.visibility = View.VISIBLE - } else { - summaryView.visibility = View.GONE - } + summaryView.visibility = View.GONE } else { valueBackup = checkBox.isChecked checkBox.isChecked = true @@ -159,9 +150,6 @@ class InteractionsTabConfiguration : TabConfiguration() { private val AccountDetails.supportsInteractions: Boolean get() = type == AccountType.TWITTER || type == AccountType.MASTODON - - private val AccountDetails.requiresStreaming: Boolean - get() = !isOfficial(context) } } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/preference/StreamingAccountsListPreference.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/preference/StreamingAccountsListPreference.kt deleted file mode 100644 index 48185f806d..0000000000 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/preference/StreamingAccountsListPreference.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2017 Mariotaku Lee - * - * 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 . - */ - -package org.mariotaku.twidere.preference - -import android.content.Context -import android.util.AttributeSet -import org.mariotaku.ktextension.set -import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT -import org.mariotaku.twidere.extension.model.isStreamingSupported -import org.mariotaku.twidere.fragment.AccountStreamingSettingsFragment -import org.mariotaku.twidere.model.AccountDetails - -class StreamingAccountsListPreference(context: Context, attrs: AttributeSet? = null) : AccountsListPreference(context, attrs) { - - override fun setupPreference(preference: AccountsListPreference.AccountItemPreference, account: AccountDetails) { - preference.isEnabled = account.isStreamingSupported - preference.fragment = AccountStreamingSettingsFragment::class.java.name - preference.extras[EXTRA_ACCOUNT] = account - } - -} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/receiver/ConnectivityStateReceiver.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/receiver/ConnectivityStateReceiver.kt index f4079496a4..2e6d65682b 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/receiver/ConnectivityStateReceiver.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/receiver/ConnectivityStateReceiver.kt @@ -24,7 +24,6 @@ import android.content.Context import android.content.Intent import android.net.ConnectivityManager import androidx.core.net.ConnectivityManagerCompat -import org.mariotaku.twidere.service.StreamingService import org.mariotaku.twidere.util.dagger.DependencyHolder class ConnectivityStateReceiver : BroadcastReceiver() { @@ -36,7 +35,6 @@ class ConnectivityStateReceiver : BroadcastReceiver() { val isNetworkMetered = ConnectivityManagerCompat.isActiveNetworkMetered(cm) val holder = DependencyHolder.get(context) holder.mediaPreloader.isNetworkMetered = isNetworkMetered - StreamingService.startOrStopService(appContext) } } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/receiver/PowerStateReceiver.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/receiver/PowerStateReceiver.kt deleted file mode 100644 index 57f2a55bc2..0000000000 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/receiver/PowerStateReceiver.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2017 Mariotaku Lee - * - * 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 . - */ - -package org.mariotaku.twidere.receiver - -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import org.mariotaku.twidere.service.StreamingService - -/** - * Created by mariotaku on 2017/3/13. - */ - -class PowerStateReceiver : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - when (intent.action) { - Intent.ACTION_POWER_CONNECTED -> { - StreamingService.startOrStopService(context) - } - Intent.ACTION_POWER_DISCONNECTED -> { - StreamingService.startOrStopService(context) - } - } - } - -} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt deleted file mode 100644 index 8c1a7716d4..0000000000 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/service/StreamingService.kt +++ /dev/null @@ -1,490 +0,0 @@ -package org.mariotaku.twidere.service - -import android.accounts.AccountManager -import android.accounts.OnAccountsUpdateListener -import android.app.PendingIntent -import android.content.Context -import android.content.Intent -import android.os.Handler -import android.os.Looper -import androidx.annotation.UiThread -import androidx.annotation.WorkerThread -import androidx.core.app.NotificationCompat -import androidx.core.net.ConnectivityManagerCompat -import org.mariotaku.abstask.library.TaskStarter -import org.mariotaku.kpreferences.get -import org.mariotaku.ktextension.addOnAccountsUpdatedListenerSafe -import org.mariotaku.ktextension.removeOnAccountsUpdatedListenerSafe -import org.mariotaku.ktextension.toLongOr -import org.mariotaku.ktextension.toNulls -import org.mariotaku.library.objectcursor.ObjectCursor -import org.mariotaku.microblog.library.MicroBlogException -import org.mariotaku.microblog.library.twitter.TwitterUserStream -import org.mariotaku.microblog.library.twitter.annotation.StreamWith -import org.mariotaku.microblog.library.twitter.model.* -import org.mariotaku.sqliteqb.library.Columns -import org.mariotaku.sqliteqb.library.Expression -import org.mariotaku.twidere.R -import org.mariotaku.twidere.TwidereConstants.LOGTAG -import org.mariotaku.twidere.annotation.AccountType -import org.mariotaku.twidere.constant.streamingEnabledKey -import org.mariotaku.twidere.constant.streamingNonMeteredNetworkKey -import org.mariotaku.twidere.constant.streamingPowerSavingKey -import org.mariotaku.twidere.extension.model.* -import org.mariotaku.twidere.extension.model.api.key -import org.mariotaku.twidere.extension.model.api.microblog.toParcelable -import org.mariotaku.twidere.extension.model.api.toParcelable -import org.mariotaku.twidere.extension.queryCount -import org.mariotaku.twidere.model.* -import org.mariotaku.twidere.model.notification.NotificationChannelSpec -import org.mariotaku.twidere.model.pagination.SinceMaxPagination -import org.mariotaku.twidere.model.util.AccountUtils -import org.mariotaku.twidere.provider.TwidereDataStore.* -import org.mariotaku.twidere.task.twitter.GetActivitiesAboutMeTask -import org.mariotaku.twidere.task.twitter.message.GetMessagesTask -import org.mariotaku.twidere.util.DataStoreUtils -import org.mariotaku.twidere.util.DebugLog -import org.mariotaku.twidere.util.IntentUtils -import org.mariotaku.twidere.util.Utils -import org.mariotaku.twidere.util.dagger.DependencyHolder -import org.mariotaku.twidere.util.dagger.GeneralComponent -import org.mariotaku.twidere.util.streaming.TwitterTimelineStreamCallback -import java.util.* -import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors -import java.util.concurrent.TimeUnit - -class StreamingService : BaseService() { - - internal lateinit var threadPoolExecutor: ExecutorService - internal lateinit var handler: Handler - - private val submittedTasks: MutableMap> = WeakHashMap() - - private val accountChangeObserver = OnAccountsUpdateListener { - if (!setupStreaming()) { - stopSelf() - } - } - - override fun onCreate() { - super.onCreate() - GeneralComponent.get(this).inject(this) - threadPoolExecutor = Executors.newCachedThreadPool { runnable -> - val thread = Thread(runnable) - thread.priority = Thread.NORM_PRIORITY - 1 - if (runnable is StreamingRunnable<*>) { - thread.name = "twidere-streaming-${runnable.account.key}" - } - return@newCachedThreadPool thread - } - handler = Handler(Looper.getMainLooper()) - AccountManager.get(this).addOnAccountsUpdatedListenerSafe(accountChangeObserver, updateImmediately = false) - } - - override fun onDestroy() { - submittedTasks.forEach { - // NOTE: IMPORTANT!!! Before Nougat, forEach { k, v -> } will crash because referenced - // BiConsumer, which is introduced in Java 8 - val (_, v) = it - v.cancel() - } - threadPoolExecutor.shutdown() - submittedTasks.clear() - removeNotification() - AccountManager.get(this).removeOnAccountsUpdatedListenerSafe(accountChangeObserver) - super.onDestroy() - } - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - if (setupStreaming()) { - return START_STICKY - } - stopSelf() - return START_NOT_STICKY - } - - override fun onBind(intent: Intent) = throw UnsupportedOperationException() - - /** - * @return True if there're enabled accounts, false if request not met and service should be stopped - */ - private fun setupStreaming(): Boolean { - if (!preferences[streamingEnabledKey]) { - return false - } - if (!activityTracker.isHomeActivityLaunched) { - return false - } - // Quit if no connection - if (connectivityManager.activeNetworkInfo?.isAvailable != true) { - return false - } - // Quit if connection metered (with preference) - val isNetworkMetered = ConnectivityManagerCompat.isActiveNetworkMetered(connectivityManager) - if (preferences[streamingNonMeteredNetworkKey] && isNetworkMetered) { - return false - } - // Quit if not charging (with preference) - val isCharging = Utils.isCharging(this) - if (preferences[streamingPowerSavingKey] && !isCharging) { - return false - } - // Quit if no streaming instance available - if (!updateStreamingInstances()) { - return false - } - showNotification() - return true - } - - private fun updateStreamingInstances(): Boolean { - val am = AccountManager.get(this) - val supportedAccounts = AccountUtils.getAllAccountDetails(am, true).filter { it.isStreamingSupported } - val supportedPrefs = supportedAccounts.map { AccountPreferences(this, preferences, it.key) } - val enabledAccounts = supportedAccounts.filter { account -> - return@filter supportedPrefs.any { - account.key == it.accountKey && it.isStreamingEnabled - } - } - - if (enabledAccounts.isEmpty()) return false - - // Remove all disabled instances - submittedTasks.forEach { - // NOTE: IMPORTANT!!! Before Nougat, forEach { k, v -> } will crash because referenced - // BiConsumer, which is introduced in Java 8 - val (k, v) = it - if (enabledAccounts.none { k == it.key } && !v.cancelled) { - v.cancel() - } - } - // Add instances if not running - enabledAccounts.forEach { account -> - val existing = submittedTasks[account.key] - if (existing == null || existing.cancelled) { - val runnable = newStreamingRunnable(account, supportedPrefs.first { - it.accountKey == account.key - }) ?: return@forEach - threadPoolExecutor.submit(runnable) - submittedTasks[account.key] = runnable - } - } - return true - } - - private fun showNotification() { - val intent = IntentUtils.settings("streaming") - val contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) - val contentTitle = getString(R.string.app_name) - val contentText = getString(R.string.timeline_streaming_running) - val builder = NotificationChannelSpec.serviceStatuses.notificationBuilder(this) - builder.setOngoing(true) - builder.setSmallIcon(R.drawable.ic_stat_streaming) - builder.setContentTitle(contentTitle) - builder.setContentText(contentText) - builder.setContentIntent(contentIntent) - builder.setCategory(NotificationCompat.CATEGORY_STATUS) - builder.priority = NotificationCompat.PRIORITY_MIN - startForeground(NOTIFICATION_SERVICE_STARTED, builder.build()) - } - - private fun removeNotification() { - stopForeground(true) - } - - private fun newStreamingRunnable(account: AccountDetails, preferences: AccountPreferences): StreamingRunnable<*>? { - when (account.type) { - AccountType.TWITTER -> { - return TwitterStreamingRunnable(this, account, preferences) - } - } - return null - } - - internal abstract class StreamingRunnable( - val context: Context, - val account: AccountDetails, - val accountPreferences: AccountPreferences - ) : Runnable { - - var cancelled: Boolean = false - private set - - override fun run() { - val instance = createStreamingInstance() - while (!cancelled && !Thread.currentThread().isInterrupted) { - try { - instance.beginStreaming() - } catch (e: MicroBlogException) { - DebugLog.w(LOGTAG, msg = "Can't stream for ${account.key}", tr = e) - } - Thread.sleep(TimeUnit.MINUTES.toMillis(1)) - } - } - - fun cancel(): Boolean { - if (cancelled) return false - cancelled = true - onCancelled() - return true - } - - abstract fun createStreamingInstance(): T - - abstract fun T.beginStreaming() - - abstract fun onCancelled() - } - - internal inner class TwitterStreamingRunnable( - context: Context, - account: AccountDetails, - accountPreferences: AccountPreferences - ) : StreamingRunnable(context, account, accountPreferences) { - - private val profileImageSize = context.getString(R.string.profile_image_size) - private val isOfficial = account.isOfficial(context) - - private var canGetInteractions: Boolean = true - private var canGetMessages: Boolean = true - - private val interactionsTimeoutRunnable = Runnable { - canGetInteractions = true - } - - private val messagesTimeoutRunnable = Runnable { - canGetMessages = true - } - - val callback = object : TwitterTimelineStreamCallback(account.key.id) { - - private var lastStatusTimestamps = LongArray(2) - - private var homeInsertGap = false - private var interactionsInsertGap = false - - private var lastActivityAboutMe: ParcelableActivity? = null - - override fun onConnected(): Boolean { - homeInsertGap = true - interactionsInsertGap = true - return true - } - - override fun onHomeTimeline(status: Status): Boolean { - if (!accountPreferences.isStreamHomeTimelineEnabled) { - homeInsertGap = true - return false - } - val parcelableStatus = status.toParcelable(account, profileImageSize = profileImageSize) - parcelableStatus.is_gap = homeInsertGap - - val currentTimeMillis = System.currentTimeMillis() - if (lastStatusTimestamps[0] >= parcelableStatus.timestamp) { - val extraValue = (currentTimeMillis - lastStatusTimestamps[1]).coerceAtMost(499) - parcelableStatus.position_key = parcelableStatus.timestamp + extraValue - } else { - parcelableStatus.position_key = parcelableStatus.timestamp - } - parcelableStatus.inserted_date = currentTimeMillis - - lastStatusTimestamps[0] = parcelableStatus.position_key - lastStatusTimestamps[1] = parcelableStatus.inserted_date - - val values = ObjectCursor.valuesCreatorFrom(ParcelableStatus::class.java) - .create(parcelableStatus) - context.contentResolver.insert(Statuses.CONTENT_URI, values) - homeInsertGap = false - return true - } - - override fun onActivityAboutMe(activity: Activity): Boolean { - if (!accountPreferences.isStreamInteractionsEnabled) { - interactionsInsertGap = true - return false - } - if (isOfficial) { - // Wait for 30 seconds to avoid rate limit - if (canGetInteractions) { - handler.post { getInteractions() } - canGetInteractions = false - handler.postDelayed(interactionsTimeoutRunnable, TimeUnit.SECONDS.toMillis(30)) - } - } else { - val insertGap: Boolean - if (activity.action in Activity.Action.MENTION_ACTIONS) { - insertGap = interactionsInsertGap - interactionsInsertGap = false - } else { - insertGap = false - } - val curActivity = activity.toParcelable(account, insertGap, profileImageSize) - curActivity.account_color = account.color - curActivity.position_key = curActivity.timestamp - var updateId = -1L - if (curActivity.action !in Activity.Action.MENTION_ACTIONS) { - /* Merge two activities if: - * * Not mention/reply/quote - * * Same action - * * Same source or target or target object - */ - val lastActivity = this.lastActivityAboutMe - if (lastActivity != null && curActivity.action == lastActivity.action) { - if (curActivity.reachedCountLimit) { - // Skip if more than 10 sources/targets/target_objects - } else if (curActivity.isSameSources(lastActivity)) { - curActivity.prependTargets(lastActivity) - curActivity.prependTargetObjects(lastActivity) - updateId = lastActivity._id - } else if (curActivity.isSameTarget(lastActivity)) { - curActivity.prependSources(lastActivity) - curActivity.prependTargets(lastActivity) - updateId = lastActivity._id - } else if (curActivity.isSameTargetObject(lastActivity)) { - curActivity.prependSources(lastActivity) - curActivity.prependTargets(lastActivity) - updateId = lastActivity._id - } - if (updateId > 0) { - curActivity.min_position = lastActivity.min_position - curActivity.min_sort_position = lastActivity.min_sort_position - } - } - } - val values = ObjectCursor.valuesCreatorFrom(ParcelableActivity::class.java) - .create(curActivity) - val resolver = context.contentResolver - if (updateId > 0) { - val where = Expression.equals(Activities._ID, updateId).sql - resolver.update(Activities.AboutMe.CONTENT_URI, values, where, null) - curActivity._id = updateId - } else { - val uri = resolver.insert(Activities.AboutMe.CONTENT_URI, values) - if (uri != null) { - curActivity._id = uri.lastPathSegment.toLongOr(-1L) - } - } - lastActivityAboutMe = curActivity - } - return true - } - - @WorkerThread - override fun onDirectMessage(directMessage: DirectMessage): Boolean { - if (!accountPreferences.isStreamDirectMessagesEnabled) { - return false - } - if (canGetMessages) { - handler.post { getMessages() } - canGetMessages = false - val timeout = TimeUnit.SECONDS.toMillis(if (isOfficial) 30 else 90) - handler.postDelayed(messagesTimeoutRunnable, timeout) - } - return true - } - - override fun onAllStatus(status: Status) { - if (!accountPreferences.isStreamNotificationUsersEnabled) { - return - } - val user = status.user ?: return - val userKey = user.key - val where = Expression.and(Expression.equalsArgs(CachedRelationships.ACCOUNT_KEY), - Expression.equalsArgs(CachedRelationships.USER_KEY), - Expression.equals(CachedRelationships.NOTIFICATIONS_ENABLED, 1)).sql - val whereArgs = arrayOf(account.key.toString(), userKey.toString()) - if (context.contentResolver.queryCount(CachedRelationships.CONTENT_URI, - where, whereArgs) <= 0) return - - contentNotificationManager.showUserNotification(account.key, status, userKey) - } - - override fun onStatusDeleted(event: DeletionEvent): Boolean { - val deleteWhere = Expression.and(Expression.likeRaw(Columns.Column(Statuses.ACCOUNT_KEY), "'%@'||?"), - Expression.equalsArgs(Columns.Column(Statuses.ID))).sql - val deleteWhereArgs = arrayOf(account.key.host, event.id) - context.contentResolver.delete(Statuses.CONTENT_URI, deleteWhere, deleteWhereArgs) - return true - } - - override fun onDisconnectNotice(code: Int, reason: String?): Boolean { - disconnect() - return true - } - - override fun onException(ex: Throwable): Boolean { - DebugLog.w(LOGTAG, msg = "Exception for ${account.key}", tr = ex) - return true - } - - override fun onUnhandledEvent(obj: TwitterStreamObject, json: String) { - DebugLog.d(LOGTAG, msg = "Unhandled event ${obj.determine()} for ${account.key}: $json") - } - - @UiThread - private fun getInteractions() { - val task = GetActivitiesAboutMeTask(context) - task.params = object : RefreshTaskParam { - override val accountKeys: Array = arrayOf(account.key) - - override val pagination by lazy { - val keys = accountKeys.toNulls() - val sinceIds = DataStoreUtils.getRefreshNewestActivityMaxPositions(context, - Activities.AboutMe.CONTENT_URI, keys) - val sinceSortIds = DataStoreUtils.getRefreshNewestActivityMaxSortPositions(context, - Activities.AboutMe.CONTENT_URI, keys) - return@lazy Array(keys.size) { idx -> - SinceMaxPagination.sinceId(sinceIds[idx], sinceSortIds[idx]) - } - } - - } - TaskStarter.execute(task) - } - - @UiThread - private fun getMessages() { - val task = GetMessagesTask(context) - task.params = object : GetMessagesTask.RefreshMessagesTaskParam(context) { - override val accountKeys: Array = arrayOf(account.key) - } - TaskStarter.execute(task) - } - } - - override fun createStreamingInstance(): TwitterUserStream { - return account.newMicroBlogInstance(context, cls = TwitterUserStream::class.java) - } - - override fun TwitterUserStream.beginStreaming() { - getUserStream(StreamWith.USER, callback) - } - - override fun onCancelled() { - callback.disconnect() - } - - } - - companion object { - - private val NOTIFICATION_SERVICE_STARTED = 1 - - fun startOrStopService(context: Context) { - val streamingIntent = Intent(context, StreamingService::class.java) - val holder = DependencyHolder.get(context) - try { - if (holder.activityTracker.isHomeActivityLaunched) { - context.startService(streamingIntent) - } else { - context.stopService(streamingIntent) - } - } catch (e: IllegalStateException) { - // This shouldn't happen, catch it. - } - } - } - -} - diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/dagger/GeneralComponent.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/dagger/GeneralComponent.kt index 0c8133215e..2bbb113d6e 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/dagger/GeneralComponent.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/util/dagger/GeneralComponent.kt @@ -144,8 +144,6 @@ interface GeneralComponent { fun inject(fragment: ExoPlayerPageFragment) - fun inject(service: StreamingService) - fun inject(service: BaseService) fun inject(activity: MainActivity) diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/streaming/FanfouTimelineStreamCallback.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/streaming/FanfouTimelineStreamCallback.kt deleted file mode 100644 index 97ee74e9cd..0000000000 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/streaming/FanfouTimelineStreamCallback.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2017 Mariotaku Lee - * - * 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 . - */ - -package org.mariotaku.twidere.util.streaming - -import org.mariotaku.microblog.library.fanfou.callback.SimpleFanfouUserStreamCallback -import org.mariotaku.microblog.library.twitter.model.Activity -import org.mariotaku.microblog.library.twitter.model.InternalActivityCreator -import org.mariotaku.microblog.library.twitter.model.Status -import org.mariotaku.microblog.library.twitter.model.User -import java.util.* - -/** - * Created by mariotaku on 2017/3/11. - */ - -abstract class FanfouTimelineStreamCallback( - val accountId: String -) : SimpleFanfouUserStreamCallback() { - - override fun onStatusCreation(createdAt: Date, source: User, target: User?, status: Status): Boolean { - var handled = false - if (target == null) { - handled = handled or onHomeTimeline(status) - } - if (target?.id == accountId) { - handled = handled or onActivityAboutMe(InternalActivityCreator.status(status, accountId)) - } - return handled - } - - protected abstract fun onHomeTimeline(status: Status): Boolean - - protected abstract fun onActivityAboutMe(activity: Activity): Boolean -} diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/util/streaming/TwitterTimelineStreamCallback.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/util/streaming/TwitterTimelineStreamCallback.kt deleted file mode 100644 index 6fe4d86f1d..0000000000 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/util/streaming/TwitterTimelineStreamCallback.kt +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Twidere - Twitter client for Android - * - * Copyright (C) 2012-2017 Mariotaku Lee - * - * 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 . - */ - -package org.mariotaku.twidere.util.streaming - -import androidx.annotation.WorkerThread -import org.mariotaku.microblog.library.twitter.callback.SimpleUserStreamCallback -import org.mariotaku.microblog.library.twitter.model.* -import java.util.* - -/** - * Created by mariotaku on 2017/3/10. - */ -@WorkerThread -abstract class TwitterTimelineStreamCallback(val accountId: String) : SimpleUserStreamCallback() { - - private val friends = mutableSetOf() - - final override fun onFriendList(friendIds: Array): Boolean { - friends.addAll(friendIds) - return true - } - - final override fun onStatus(status: Status): Boolean { - val userId = status.user.id - var handled = false - if (accountId == userId || userId in friends) { - handled = handled or onHomeTimeline(status) - } - if (status.inReplyToUserId == accountId) { - // Reply - handled = handled or onActivityAboutMe(InternalActivityCreator.status(status, accountId)) - } else if (userId != accountId && status.retweetedStatus?.user?.id == accountId) { - // Retweet - handled = handled or onActivityAboutMe(InternalActivityCreator.retweet(status)) - } else if (status.userMentionEntities?.find { it.id == accountId } != null) { - // Mention - handled = handled or onActivityAboutMe(InternalActivityCreator.status(status, accountId)) - } - onAllStatus(status) - return handled - } - - final override fun onFollow(createdAt: Date, source: User, target: User): Boolean { - if (source.id == accountId) { - friends.add(target.id) - return true - } else if (target.id == accountId) { - // Dispatch follow activity - return onActivityAboutMe(InternalActivityCreator.follow(createdAt, source, target)) - } - return false - } - - final override fun onFavorite(createdAt: Date, source: User, target: User, - targetObject: Status): Boolean { - if (source.id == accountId) { - // TODO Update my favorite status - } else if (target.id == accountId) { - // Dispatch favorite activity - return onActivityAboutMe(InternalActivityCreator.targetStatus(Activity.Action.FAVORITE, - createdAt, source, targetObject)) - } - return true - } - - final override fun onUnfollow(createdAt: Date, source: User, followedUser: User): Boolean { - if (source.id == accountId) { - friends.remove(followedUser.id) - return true - } - return false - } - - final override fun onQuotedTweet(createdAt: Date, source: User, target: User, targetObject: Status): Boolean { - if (source.id == accountId) { - return false - } else if (target.id == accountId) { - // Dispatch activity - return onActivityAboutMe(InternalActivityCreator.targetStatus(Activity.Action.QUOTE, - createdAt, source, targetObject)) - } - return true - } - - final override fun onFavoritedRetweet(createdAt: Date, source: User, target: User, targetObject: Status): Boolean { - if (source.id == accountId) { - return false - } else if (target.id == accountId) { - // Dispatch activity - return onActivityAboutMe(InternalActivityCreator.targetStatus(Activity.Action.FAVORITED_RETWEET, - createdAt, source, targetObject)) - } - return true - } - - final override fun onRetweetedRetweet(createdAt: Date, source: User, target: User, targetObject: Status): Boolean { - if (source.id == accountId) { - return false - } else if (target.id == accountId) { - // Dispatch activity - return onActivityAboutMe(InternalActivityCreator.targetStatus(Activity.Action.RETWEETED_RETWEET, - createdAt, source, targetObject)) - } - return false - } - - final override fun onUserListMemberAddition(createdAt: Date, source: User, target: User, targetObject: UserList): Boolean { - if (source.id == accountId) { - return false - } else if (target.id == accountId) { - // Dispatch activity - return onActivityAboutMe(InternalActivityCreator.targetObject(Activity.Action.LIST_MEMBER_ADDED, - createdAt, source, target, targetObject)) - } - return false - } - - @WorkerThread - protected abstract fun onHomeTimeline(status: Status): Boolean - - @WorkerThread - protected abstract fun onActivityAboutMe(activity: Activity): Boolean - - @WorkerThread - abstract override fun onDirectMessage(directMessage: DirectMessage): Boolean - - @WorkerThread - protected open fun onAllStatus(status: Status) { - } -} diff --git a/twidere/src/main/res/values/strings.xml b/twidere/src/main/res/values/strings.xml index f5151ac854..c8523f9dce 100644 --- a/twidere/src/main/res/values/strings.xml +++ b/twidere/src/main/res/values/strings.xml @@ -345,8 +345,6 @@ Empty content - Enable streaming - Please check your system date & time settings. Error: %s This device is not compatible with Twidere, upgrade to latest Android OS is recommended.\nYou can send information below to help me report this issue to device manufacturer. @@ -575,7 +573,6 @@ Tweets and replies Tweets and retweets Tweets, retweets and replies - Streaming service Translate from %s Translated to %s Translation @@ -711,7 +708,6 @@ Account permission is required No account selected No user selected - Only available when streaming is on, and not 100% reliable. Press again to close Profile background image updated Profile banner image updated @@ -803,7 +799,6 @@ Messages Subscriptions Updates - Service statuses %s sent you a direct message. %1$s sent you %2$d direct messages. %1$s and %2$d others sent you %3$d direct messages. @@ -886,21 +881,17 @@ Rename existing accounts? Enable for faster refresh interval, increases power usage on Android 5.0+ Stop auto refresh when battery is low - Press HOME instead of BACK to keep streaming open Open links with in-app browser (Powered by Chrome) Upper limit of items stored in databases for each account, set to a smaller value to save space and increase loading speed. Show confirmation before favoriting a tweet Show confirmation before liking a tweet Preload media only on free networks like Wi-Fi - Streaming only on free networks like Wi-Fi - Streaming only when charging When \"Remember position\" enabled Now you can set location separately in tab settings. Accounts Advanced Compatibility mode Power saving mode - Background streaming In-app browser Database size limit Favorite confirmation @@ -919,10 +910,6 @@ App language Portrait Storage - Streaming content - Enable streaming - Streaming on free network - Power saving mode Tablet mode Text size Timeline positions @@ -1092,7 +1079,6 @@ Interface Notifications Refresh - Streaming Share format \"[TITLE]\" = Content title\n\"[TEXT]\" = Content text @@ -1146,20 +1132,11 @@ Retweet - Users turned "Notifications" on, not 100% reliable. - Home - Interactions - Messages - Notification enabled users - - Streaming - Style Subscribed to list \"%s\". Account not supported - Full interactions available only when streaming enabled Swipe down to refresh @@ -1200,7 +1177,6 @@ %1$s ยท %2$s - Timeline streaming running Timeline sync service About @@ -1263,7 +1239,6 @@ Tweets Tweets & replies Tweets scheduling - Streaming Name URL %1$s: %2$s diff --git a/twidere/src/main/res/xml/preferences_account_streaming.xml b/twidere/src/main/res/xml/preferences_account_streaming.xml deleted file mode 100644 index c7bdc1ed14..0000000000 --- a/twidere/src/main/res/xml/preferences_account_streaming.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/twidere/src/main/res/xml/preferences_streaming.xml b/twidere/src/main/res/xml/preferences_streaming.xml deleted file mode 100644 index 9ae604b4f5..0000000000 --- a/twidere/src/main/res/xml/preferences_streaming.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file