fixed unix epoch converter
This commit is contained in:
parent
0cc43f5b9c
commit
3a60dd88c0
|
@ -46,7 +46,7 @@ public final class ResponseList$$JsonObjectMapper<T> extends JsonMapper<Response
|
|||
if (jsonParser.getCurrentToken() == null) {
|
||||
jsonParser.nextToken();
|
||||
}
|
||||
if (m84ClassJsonMapper instanceof ScheduledStatus$$JsonObjectMapper) {
|
||||
if (jsonParser.getCurrentToken() == JsonToken.START_OBJECT) {
|
||||
ResponseList<T> instance = new ResponseList<>();
|
||||
while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
|
||||
String fieldName = jsonParser.getCurrentName();
|
||||
|
@ -56,10 +56,10 @@ public final class ResponseList$$JsonObjectMapper<T> extends JsonMapper<Response
|
|||
}
|
||||
return instance;
|
||||
} else if (jsonParser.getCurrentToken() != JsonToken.START_ARRAY) {
|
||||
jsonParser.skipChildren();
|
||||
return null;
|
||||
return new ResponseList<>(m84ClassJsonMapper.parseList(jsonParser));
|
||||
}
|
||||
return new ResponseList<>(m84ClassJsonMapper.parseList(jsonParser));
|
||||
jsonParser.skipChildren();
|
||||
throw new IOException("Unsupported object");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,34 +19,24 @@
|
|||
|
||||
package org.mariotaku.twidere.model.util;
|
||||
|
||||
import com.bluelinelabs.logansquare.typeconverters.TypeConverter;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.bluelinelabs.logansquare.typeconverters.LongBasedTypeConverter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 2017/3/25.
|
||||
*/
|
||||
|
||||
public class UnixEpochMillisDateConverter implements TypeConverter<Date> {
|
||||
public class UnixEpochMillisDateConverter extends LongBasedTypeConverter<Date> {
|
||||
@Override
|
||||
public Date parse(final JsonParser jsonParser) throws IOException {
|
||||
long value = jsonParser.nextLongValue(-1);
|
||||
return new Date(value);
|
||||
public Date getFromLong(final long l) {
|
||||
return new Date(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Date object, final String fieldName,
|
||||
final boolean writeFieldNameForObject, final JsonGenerator jsonGenerator) throws IOException {
|
||||
if (writeFieldNameForObject) {
|
||||
jsonGenerator.writeFieldName(fieldName);
|
||||
}
|
||||
if (object == null) {
|
||||
jsonGenerator.writeNull();
|
||||
} else {
|
||||
jsonGenerator.writeNumber(object.getTime());
|
||||
}
|
||||
public long convertToLong(final Date object) {
|
||||
if (object == null) return -1;
|
||||
return object.getTime();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,11 +19,8 @@
|
|||
|
||||
package org.mariotaku.twidere.model.util;
|
||||
|
||||
import com.bluelinelabs.logansquare.typeconverters.TypeConverter;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.bluelinelabs.logansquare.typeconverters.LongBasedTypeConverter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -31,23 +28,16 @@ import java.util.concurrent.TimeUnit;
|
|||
* Created by mariotaku on 2017/3/25.
|
||||
*/
|
||||
|
||||
public class UnixEpochSecondDateConverter implements TypeConverter<Date> {
|
||||
public class UnixEpochSecondDateConverter extends LongBasedTypeConverter<Date> {
|
||||
@Override
|
||||
public Date parse(final JsonParser jsonParser) throws IOException {
|
||||
long value = jsonParser.nextLongValue(-1);
|
||||
return new Date(TimeUnit.MILLISECONDS.toSeconds(value));
|
||||
public Date getFromLong(final long l) {
|
||||
return new Date(TimeUnit.SECONDS.toMillis(l));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Date object, final String fieldName,
|
||||
final boolean writeFieldNameForObject, final JsonGenerator jsonGenerator) throws IOException {
|
||||
if (writeFieldNameForObject) {
|
||||
jsonGenerator.writeFieldName(fieldName);
|
||||
}
|
||||
if (object == null) {
|
||||
jsonGenerator.writeNull();
|
||||
} else {
|
||||
jsonGenerator.writeNumber(TimeUnit.SECONDS.toMillis(object.getTime()));
|
||||
}
|
||||
public long convertToLong(final Date object) {
|
||||
if (object == null) return -1;
|
||||
return TimeUnit.MILLISECONDS.toSeconds(object.getTime());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -253,6 +253,7 @@ public class ParcelableMediaUtils {
|
|||
return ParcelableMedia.Type.UNKNOWN;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static ParcelableMedia image(final String url) {
|
||||
ParcelableMedia media = new ParcelableMedia();
|
||||
media.type = ParcelableMedia.Type.IMAGE;
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view.holder;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.view.CardMediaContainer;
|
||||
import org.mariotaku.twidere.view.iface.IColorLabelView;
|
||||
|
||||
public class DraftViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
public final IColorLabelView content;
|
||||
public final TextView text;
|
||||
public final TextView time;
|
||||
public CardMediaContainer mediaPreviewContainer;
|
||||
|
||||
public DraftViewHolder(final View itemView) {
|
||||
super(itemView);
|
||||
content = (IColorLabelView) itemView.findViewById(R.id.content);
|
||||
text = (TextView) itemView.findViewById(R.id.text);
|
||||
time = (TextView) itemView.findViewById(R.id.time);
|
||||
mediaPreviewContainer = (CardMediaContainer) itemView.findViewById(R.id.media_preview_container);
|
||||
}
|
||||
|
||||
public void setTextSize(final float textSize) {
|
||||
text.setTextSize(textSize);
|
||||
time.setTextSize(textSize * 0.75f);
|
||||
}
|
||||
|
||||
}
|
|
@ -22,20 +22,15 @@ package org.mariotaku.twidere.adapter
|
|||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.support.v4.widget.SimpleCursorAdapter
|
||||
import android.support.v7.widget.RecyclerViewAccessor
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.bumptech.glide.RequestManager
|
||||
import org.mariotaku.kpreferences.get
|
||||
import org.mariotaku.library.objectcursor.ObjectCursor
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.constant.mediaPreviewStyleKey
|
||||
import org.mariotaku.twidere.extension.model.getActionName
|
||||
import org.mariotaku.twidere.model.Draft
|
||||
import org.mariotaku.twidere.model.draft.StatusObjectExtras
|
||||
import org.mariotaku.twidere.model.util.ParcelableMediaUtils
|
||||
import org.mariotaku.twidere.util.DataStoreUtils
|
||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper
|
||||
import org.mariotaku.twidere.util.Utils
|
||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
|
||||
import org.mariotaku.twidere.view.holder.DraftViewHolder
|
||||
import javax.inject.Inject
|
||||
|
@ -43,7 +38,7 @@ import javax.inject.Inject
|
|||
class DraftsAdapter(
|
||||
context: Context,
|
||||
val requestManager: RequestManager
|
||||
) : SimpleCursorAdapter(context, R.layout.list_item_draft, null, arrayOfNulls<String>(0), IntArray(0), 0) {
|
||||
) : SimpleCursorAdapter(context, DraftViewHolder.layoutResource, null, emptyArray(), intArrayOf(), 0) {
|
||||
|
||||
@Inject
|
||||
lateinit var preferences: SharedPreferencesWrapper
|
||||
|
@ -55,6 +50,7 @@ class DraftsAdapter(
|
|||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private var indices: ObjectCursor.CursorIndices<Draft>? = null
|
||||
|
||||
init {
|
||||
|
@ -63,59 +59,19 @@ class DraftsAdapter(
|
|||
}
|
||||
|
||||
override fun bindView(view: View, context: Context, cursor: Cursor) {
|
||||
val holder = view.tag as DraftViewHolder
|
||||
val draft = indices!!.newObject(cursor)
|
||||
|
||||
val accountKeys = draft.account_keys
|
||||
val actionType: String = draft.action_type ?: Draft.Action.UPDATE_STATUS
|
||||
val actionName = draft.getActionName(context)
|
||||
var summaryText: String? = null
|
||||
when (actionType) {
|
||||
Draft.Action.SEND_DIRECT_MESSAGE, Draft.Action.SEND_DIRECT_MESSAGE_COMPAT,
|
||||
Draft.Action.UPDATE_STATUS, Draft.Action.UPDATE_STATUS_COMPAT_1,
|
||||
Draft.Action.UPDATE_STATUS_COMPAT_2, Draft.Action.REPLY, Draft.Action.QUOTE -> {
|
||||
val media = ParcelableMediaUtils.fromMediaUpdates(draft.media)
|
||||
holder.mediaPreviewContainer.visibility = View.VISIBLE
|
||||
holder.mediaPreviewContainer.displayMedia(requestManager = requestManager,
|
||||
media = media)
|
||||
}
|
||||
Draft.Action.FAVORITE, Draft.Action.RETWEET -> {
|
||||
val extras = draft.action_extras as? StatusObjectExtras
|
||||
if (extras != null) {
|
||||
summaryText = extras.status.text_unescaped
|
||||
}
|
||||
holder.mediaPreviewContainer.visibility = View.GONE
|
||||
}
|
||||
else -> {
|
||||
holder.mediaPreviewContainer.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
if (accountKeys != null) {
|
||||
holder.content.drawEnd(*DataStoreUtils.getAccountColors(context, accountKeys))
|
||||
} else {
|
||||
holder.content.drawEnd()
|
||||
}
|
||||
holder.setTextSize(textSize)
|
||||
if (summaryText != null) {
|
||||
holder.text.text = summaryText
|
||||
} else if (draft.text.isNullOrEmpty()) {
|
||||
holder.text.setText(R.string.empty_content)
|
||||
} else {
|
||||
holder.text.text = draft.text
|
||||
}
|
||||
val holder = view.tag as DraftViewHolder
|
||||
RecyclerViewAccessor.setLayoutPosition(holder, cursor.position)
|
||||
|
||||
if (draft.timestamp > 0) {
|
||||
val timeString = Utils.formatSameDayTime(context, draft.timestamp)
|
||||
holder.time.text = context.getString(R.string.action_name_saved_at_time, actionName, timeString)
|
||||
} else {
|
||||
holder.time.text = actionName
|
||||
}
|
||||
holder.display(context, requestManager, draft)
|
||||
}
|
||||
|
||||
override fun newView(context: Context?, cursor: Cursor?, parent: ViewGroup): View {
|
||||
override fun newView(context: Context, cursor: Cursor, parent: ViewGroup): View {
|
||||
val view = super.newView(context, cursor, parent)
|
||||
if (view.tag !is DraftViewHolder) {
|
||||
view.tag = DraftViewHolder(view).apply {
|
||||
this.setTextSize(textSize)
|
||||
this.mediaPreviewContainer.style = mediaPreviewStyle
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2017 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.view.holder
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.View
|
||||
import com.bumptech.glide.RequestManager
|
||||
import kotlinx.android.synthetic.main.list_item_draft.view.*
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.extension.model.getActionName
|
||||
import org.mariotaku.twidere.model.Draft
|
||||
import org.mariotaku.twidere.model.draft.StatusObjectExtras
|
||||
import org.mariotaku.twidere.model.util.ParcelableMediaUtils
|
||||
import org.mariotaku.twidere.util.DataStoreUtils
|
||||
import org.mariotaku.twidere.util.Utils
|
||||
|
||||
class DraftViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
internal val contentView = itemView.content
|
||||
internal val textView = itemView.text
|
||||
internal val timeView = itemView.time
|
||||
internal val mediaPreviewContainer = itemView.mediaPreviewContainer
|
||||
|
||||
fun display(context: Context, requestManager: RequestManager, draft: Draft) {
|
||||
val accountKeys = draft.account_keys
|
||||
val actionType: String = draft.action_type ?: Draft.Action.UPDATE_STATUS
|
||||
val actionName = draft.getActionName(context)
|
||||
var summaryText: String? = null
|
||||
when (actionType) {
|
||||
Draft.Action.SEND_DIRECT_MESSAGE, Draft.Action.SEND_DIRECT_MESSAGE_COMPAT,
|
||||
Draft.Action.UPDATE_STATUS, Draft.Action.UPDATE_STATUS_COMPAT_1,
|
||||
Draft.Action.UPDATE_STATUS_COMPAT_2, Draft.Action.REPLY, Draft.Action.QUOTE -> {
|
||||
val media = ParcelableMediaUtils.fromMediaUpdates(draft.media)
|
||||
mediaPreviewContainer.visibility = View.VISIBLE
|
||||
mediaPreviewContainer.displayMedia(requestManager = requestManager,
|
||||
media = media)
|
||||
}
|
||||
Draft.Action.FAVORITE, Draft.Action.RETWEET -> {
|
||||
val extras = draft.action_extras as? StatusObjectExtras
|
||||
if (extras != null) {
|
||||
summaryText = extras.status.text_unescaped
|
||||
}
|
||||
mediaPreviewContainer.visibility = View.GONE
|
||||
}
|
||||
else -> {
|
||||
mediaPreviewContainer.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
if (accountKeys != null) {
|
||||
contentView.drawEnd(*DataStoreUtils.getAccountColors(context, accountKeys))
|
||||
} else {
|
||||
contentView.drawEnd()
|
||||
}
|
||||
if (summaryText != null) {
|
||||
textView.text = summaryText
|
||||
} else if (draft.text.isNullOrEmpty()) {
|
||||
textView.setText(R.string.empty_content)
|
||||
} else {
|
||||
textView.text = draft.text
|
||||
}
|
||||
|
||||
if (draft.timestamp > 0) {
|
||||
val timeString = Utils.formatSameDayTime(context, draft.timestamp)
|
||||
timeView.text = context.getString(R.string.action_name_saved_at_time, actionName, timeString)
|
||||
} else {
|
||||
timeView.text = actionName
|
||||
}
|
||||
}
|
||||
|
||||
fun setTextSize(textSize: Float) {
|
||||
textView.textSize = textSize
|
||||
timeView.textSize = textSize * 0.75f
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
const val layoutResource = R.layout.list_item_draft
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -26,20 +26,30 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:background="?android:activatedBackgroundIndicator"
|
||||
android:descendantFocusability="blocksDescendants"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="?android:listPreferredItemHeightSmall"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/element_spacing_normal"
|
||||
app:backgroundTint="?colorControlActivated"
|
||||
app:ignorePadding="true"
|
||||
tools:context=".adapter.DraftsAdapter">
|
||||
|
||||
<org.mariotaku.twidere.view.FixedTextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/element_spacing_small"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="@string/sample_status_text"/>
|
||||
|
||||
<org.mariotaku.twidere.view.CardMediaContainer
|
||||
android:id="@+id/media_preview_container"
|
||||
android:id="@+id/mediaPreviewContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignLeft="@+id/profileContainer"
|
||||
android:layout_alignStart="@+id/profileContainer"
|
||||
android:layout_below="@id/profileContainer"
|
||||
android:layout_marginTop="@dimen/element_spacing_normal"
|
||||
android:horizontalSpacing="@dimen/element_spacing_xsmall"
|
||||
android:verticalSpacing="@dimen/element_spacing_xsmall">
|
||||
|
||||
|
@ -47,27 +57,14 @@
|
|||
|
||||
</org.mariotaku.twidere.view.CardMediaContainer>
|
||||
|
||||
<org.mariotaku.twidere.view.FixedTextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="?android:listPreferredItemHeightSmall"
|
||||
android:paddingBottom="@dimen/element_spacing_normal"
|
||||
android:paddingLeft="@dimen/element_spacing_normal"
|
||||
android:paddingRight="@dimen/element_spacing_normal"
|
||||
android:paddingTop="@dimen/element_spacing_normal"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"/>
|
||||
|
||||
<org.mariotaku.twidere.view.FixedTextView
|
||||
android:id="@+id/time"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/element_spacing_normal"
|
||||
android:paddingLeft="@dimen/element_spacing_normal"
|
||||
android:paddingRight="@dimen/element_spacing_normal"
|
||||
android:padding="@dimen/element_spacing_small"
|
||||
android:textAppearance="?android:textAppearanceSmall"
|
||||
android:textColor="?android:textColorPrimary"/>
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:text="12:00 April 1"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<!-- [verb] Action for blocking user -->
|
||||
<string name="action_block">Block</string>
|
||||
<string name="action_blocking">blocking</string>
|
||||
<string name="action_buffer_disconnect">Disconnect from Buffer</string>
|
||||
<string name="action_buffer_settings">Settings</string>
|
||||
<!-- [verb] Action for cancelling (deleting) a retweet-->
|
||||
<string name="action_cancel_retweet">Cancel retweet</string>
|
||||
|
@ -516,6 +517,7 @@
|
|||
<string name="label_buffer_accounts">Buffer accounts</string>
|
||||
<string name="label_data_provider">Twidere database provider</string>
|
||||
<string name="label_filters_subscription">Subscription</string>
|
||||
<string name="label_format_buffer_time_source"><xliff:g example="12:00, April 1" id="time">%1$s</xliff:g> via <xliff:g example="api" id="source">%2$s</xliff:g></string>
|
||||
<string name="label_location_your_coarse_location">Your coarse location</string>
|
||||
<string name="label_media">Media</string>
|
||||
<string name="label_original_status">Original tweet</string>
|
||||
|
@ -599,6 +601,7 @@
|
|||
<string name="message_destroy_conversation_confirm">Leave this conversation?</string>
|
||||
<string name="message_direct_message_deleted">Direct message deleted.</string>
|
||||
<string name="message_direct_message_sent">Direct message sent.</string>
|
||||
<string name="message_error_buffer_connection_failed">Unable to connect to Buffer</string>
|
||||
<string name="message_error_buffer_media_not_supported">Schedule media with Buffer is not yet supported</string>
|
||||
<string name="message_error_invalid_account">Some account data are corrupted, Twidere will remove those accounts to prevent crash.</string>
|
||||
<string name="message_format_compose_message_convert_to_status">This tweet will be sent as a message to <xliff:g id="name">%1$s</xliff:g>, continue? Converting to a normal tweet uses an extra character.</string>
|
||||
|
@ -610,6 +613,7 @@
|
|||
<string name="message_format_participants_join_added"><xliff:g example="Sender" id="sender">%1$s</xliff:g> added <xliff:g example="Recipient" id="recipient">%2$s</xliff:g></string>
|
||||
<string name="message_format_participants_leave"><xliff:g example="User" id="name">%1$s</xliff:g> left</string>
|
||||
<string name="message_format_sender_time"><xliff:g example="User" id="sender">%1$s</xliff:g> · <xliff:g example="12:00" id="time">%2$s</xliff:g></string>
|
||||
<string name="message_info_buffer_queue_empty">Buffer queue is empty</string>
|
||||
<string name="message_join_conversation">Joined conversation.</string>
|
||||
<string name="message_permission_request_compose_location">Twidere needs location permission for adding location to tweets.</string>
|
||||
<string name="message_permission_request_save_media">Twidere needs storage permission for saving media.</string>
|
||||
|
@ -1266,5 +1270,5 @@
|
|||
<string name="users_statuses">User\'s tweets</string>
|
||||
|
||||
<string name="vibration">Vibration</string>
|
||||
<string name="action_buffer_disconnect">Disconnect from Buffer</string>
|
||||
<string name="label_buffer_due_at_no_time">No time</string>
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue