bug fix, layout fix, code cleanup

This commit is contained in:
nuclearfog 2023-12-03 13:40:28 +01:00
parent 85e8ff789e
commit ca18647dcd
No known key found for this signature in database
GPG Key ID: 43E45B82006BC9D5
21 changed files with 103 additions and 52 deletions

View File

@ -64,6 +64,7 @@ dependencies {
implementation 'com.github.duanhong169:checkerboarddrawable:1.0.2'
implementation 'com.kyleduo.switchbutton:library:2.1.0'
implementation 'com.github.UnifiedPush:android-connector:2.1.1'
//noinspection GradleDependency
implementation 'com.google.android.material:material:1.9.0'
implementation 'jp.wasabeef:picasso-transformations:2.4.0'
implementation 'net.danlew:android.joda:2.12.5'

View File

@ -270,7 +270,7 @@ public class Mastodon implements Connection {
ResponseBody body = response.body();
if (response.code() == 200 && body != null) {
JSONArray array = new JSONArray(body.string());
for (int i = 0 ; i < array.length() ; i++) {
for (int i = 0; i < array.length(); i++) {
JSONObject json = array.getJSONObject(i);
Announcement item = new MastodonAnnouncement(json);
if (settings.showAllAnnouncements() || !item.isDismissed()) {

View File

@ -1,5 +1,8 @@
package org.nuclearfog.twidda.backend.api.mastodon.impl;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@ -89,4 +92,20 @@ public class MastodonAnnouncement implements Announcement {
public Reaction[] getReactions() {
return reactions;
}
@Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof Announcement))
return false;
Announcement announcement = (Announcement) obj;
return announcement.getId() == id && announcement.getTimestamp() == getTimestamp();
}
@NonNull
@Override
public String toString() {
return "id=" + getId() + " dismissed=" + isDismissed() + " message=\"" + getMessage() + "\"";
}
}

View File

@ -50,7 +50,7 @@ public class MastodonInstance implements Instance {
JSONObject translations = configuration.getJSONObject("translation");
JSONArray mediaTypes = media.getJSONArray("supported_mime_types");
JSONArray language = json.getJSONArray("languages");
JSONObject thumbnail = json.optJSONObject( "thumbnail");
JSONObject thumbnail = json.optJSONObject("thumbnail");
JSONObject contact = json.optJSONObject("contact");
JSONObject usage = json.optJSONObject("usage");

View File

@ -10,6 +10,8 @@ import org.nuclearfog.twidda.model.Account;
import org.nuclearfog.twidda.model.WebPush;
/**
* Async class used to select or remove a login
*
* @author nuclearfog
*/
public class AccountAction extends AsyncExecutor<AccountAction.Param, AccountAction.Result> {

View File

@ -8,7 +8,7 @@ import org.nuclearfog.twidda.database.AppDatabase;
import org.nuclearfog.twidda.model.lists.Accounts;
/**
* backend loader to get login information of local accounts
* Async loader to get saved login informations
*
* @author nuclearfog
*/

View File

@ -10,7 +10,7 @@ import org.nuclearfog.twidda.backend.api.ConnectionException;
import org.nuclearfog.twidda.backend.api.ConnectionManager;
/**
* asyncloader to modify instance announcements
* Async loader to remove instance announcements
*
* @author nuclearfog
*/

View File

@ -7,7 +7,7 @@ import java.io.Serializable;
*
* @author nuclearfog
*/
public interface Announcement extends Serializable {
public interface Announcement extends Serializable, Comparable<Announcement> {
/**
* @return ID of the announcement
@ -38,4 +38,13 @@ public interface Announcement extends Serializable {
* @return user reactions of the announcement
*/
Reaction[] getReactions();
/**
*
*/
default int compareTo(Announcement announcement) {
if (announcement.getTimestamp() != getTimestamp())
return Long.compare(announcement.getTimestamp(), getTimestamp());
return Long.compare(announcement.getId(), getId());
}
}

View File

@ -16,7 +16,8 @@ public class Announcements extends LinkedList<Announcement> {
/**
*
*/
public Announcements() {}
public Announcements() {
}
/**
*

View File

@ -15,7 +15,6 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.lifecycle.ViewModelProvider;

View File

@ -50,8 +50,7 @@ public class AnnouncementAdapter extends Adapter<AnnouncementHolder> implements
@Override
public void onItemClick(int position, int type, int... extras) {
switch(type) {
switch (type) {
case ANNOUNCEMENT_DISMISS:
listener.onAnnouncementDismiss(items.get(position));
break;

View File

@ -34,6 +34,7 @@ import org.nuclearfog.twidda.ui.adapter.recyclerview.ReactionAdapter.OnReactionS
public class AnnouncementHolder extends ViewHolder implements OnClickListener, OnReactionSelected {
private TextView time, content;
private View dismissButton;
private OnHolderClickListener listener;
private GlobalSettings settings;
@ -55,7 +56,7 @@ public class AnnouncementHolder extends ViewHolder implements OnClickListener, O
adapter = new ReactionAdapter(this);
CardView card = (CardView) itemView;
ViewGroup container = itemView.findViewById(R.id.item_announcement_container);
View dismiss = itemView.findViewById(R.id.item_announcement_dismiss);
dismissButton = itemView.findViewById(R.id.item_announcement_dismiss);
RecyclerView reactionList = itemView.findViewById(R.id.item_announcement_list_reactions);
time = itemView.findViewById(R.id.item_announcement_timestamp);
content = itemView.findViewById(R.id.item_announcement_content);
@ -67,7 +68,7 @@ public class AnnouncementHolder extends ViewHolder implements OnClickListener, O
AppStyles.setTheme(container, Color.TRANSPARENT);
container.setOnClickListener(this);
dismiss.setOnClickListener(this);
dismissButton.setOnClickListener(this);
this.listener = listener;
}
@ -94,7 +95,7 @@ public class AnnouncementHolder extends ViewHolder implements OnClickListener, O
}
/**
*
* set holder content
*/
public void setContent(Announcement announcement) {
Spannable textSpan = Tagger.makeTextWithLinks(announcement.getMessage(), settings.getHighlightColor());
@ -103,6 +104,11 @@ public class AnnouncementHolder extends ViewHolder implements OnClickListener, O
emojiLoader.execute(param, textResult);
textSpan = EmojiUtils.removeTags(textSpan);
}
if (announcement.isDismissed()) {
dismissButton.setVisibility(View.GONE);
} else {
dismissButton.setVisibility(View.VISIBLE);
}
content.setText(textSpan);
time.setText(StringUtils.formatCreationTime(time.getResources(), announcement.getTimestamp()));
adapter.setItems(announcement.getReactions());

View File

@ -2,6 +2,7 @@ package org.nuclearfog.twidda.ui.dialogs;
import android.app.Activity;
import android.app.Dialog;
import android.graphics.Typeface;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
@ -15,6 +16,8 @@ import androidx.annotation.NonNull;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import java.util.regex.Pattern;
import top.defaults.colorpicker.ColorObserver;
import top.defaults.colorpicker.ColorPickerView;
@ -25,15 +28,27 @@ import top.defaults.colorpicker.ColorPickerView;
*/
public class ColorPickerDialog extends Dialog implements OnClickListener, ColorObserver, TextWatcher {
/**
* bundle key to save/restore color value
*/
private static final String KEY_COLOR = "color";
private static final String KEY_MODE = "mode";
/**
* bundle key to save/restore color type
*/
private static final String KEY_TYPE = "mode";
/**
* pattern used to check rgb hex input
*/
private static final Pattern HEX_PATTERN = Pattern.compile("[0123456789ABCDEFabcdef]{1,8}");
private ColorPickerView colorPickerView;
private EditText hexCode;
private ViewGroup root;
private OnColorSelectedListener listener;
private int mode;
private int type;
/**
* @param listener callback listener to set color
@ -55,18 +70,32 @@ public class ColorPickerDialog extends Dialog implements OnClickListener, ColorO
View cancel = findViewById(R.id.dialog_colorpicker_cancel);
hexCode.addTextChangedListener(this);
colorPickerView.subscribe(this);
confirm.setOnClickListener(this);
cancel.setOnClickListener(this);
}
@Override
protected void onStart() {
super.onStart();
colorPickerView.subscribe(this);
}
@Override
protected void onStop() {
super.onStop();
colorPickerView.unsubscribe(this);
}
@NonNull
@Override
public Bundle onSaveInstanceState() {
Bundle bundle = super.onSaveInstanceState();
bundle.putInt(KEY_COLOR, colorPickerView.getColor());
bundle.putInt(KEY_MODE, mode);
int color = colorPickerView.getColor();
bundle.putInt(KEY_COLOR, color);
bundle.putInt(KEY_TYPE, type);
return bundle;
}
@ -74,8 +103,9 @@ public class ColorPickerDialog extends Dialog implements OnClickListener, ColorO
@Override
public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mode = savedInstanceState.getInt(KEY_MODE);
colorPickerView.setInitialColor(savedInstanceState.getInt(KEY_COLOR));
int color = savedInstanceState.getInt(KEY_COLOR);
type = savedInstanceState.getInt(KEY_TYPE);
colorPickerView.setInitialColor(color);
}
@ -88,7 +118,7 @@ public class ColorPickerDialog extends Dialog implements OnClickListener, ColorO
@Override
public void onClick(View v) {
if (v.getId() == R.id.dialog_colorpicker_ok) {
listener.onColorSelected(mode, colorPickerView.getColor());
listener.onColorSelected(type, colorPickerView.getColor());
dismiss();
} else if (v.getId() == R.id.dialog_colorpicker_cancel) {
dismiss();
@ -98,6 +128,7 @@ public class ColorPickerDialog extends Dialog implements OnClickListener, ColorO
@Override
public void onColor(int color, boolean fromUser, boolean shouldPropagate) {
// only handle user input
if (fromUser) {
hexCode.setText(String.format("%08X", color));
}
@ -111,11 +142,12 @@ public class ColorPickerDialog extends Dialog implements OnClickListener, ColorO
public void show(int color, int type, boolean enableAlpha) {
if (!isShowing()) {
super.show();
this.mode = type;
this.type = type;
colorPickerView.setInitialColor(color);
colorPickerView.setEnabledAlpha(enableAlpha);
hexCode.setText(String.format("%08X", color));
AppStyles.setTheme(root);
hexCode.setTypeface(Typeface.MONOSPACE);
}
}
@ -135,7 +167,7 @@ public class ColorPickerDialog extends Dialog implements OnClickListener, ColorO
// only handle user input
if (hexCode.hasFocus()) {
String hex = s.toString();
if (hex.matches("[0123456789ABCDEFabcdef]{1,8}")) {
if (HEX_PATTERN.matcher(hex).matches()) {
colorPickerView.setInitialColor(Integer.parseUnsignedInt(hex, 16));
}
}

View File

@ -16,12 +16,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
android:gravity="center_vertical"
android:layout_margin="@dimen/dialog_colorpicker_margin_layout">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/dialog_colorpicker_margin_layout"
android:text="@string/hash"
android:lines="1"
android:textSize="@dimen/dialog_colorpicker_textsize_textview" />
@ -39,13 +39,13 @@
android:digits="0123456789ABCDEFabcdef"
android:textSize="@dimen/dialog_colorpicker_textsize_textview"
android:inputType="textNoSuggestions"
android:importantForAutofill="no"/>
android:importantForAutofill="no" />
<Button
android:id="@+id/dialog_colorpicker_cancel"
android:layout_width="wrap_content"
android:layout_height="@dimen/dialog_colorpicker_height_button"
android:layout_margin="@dimen/dialog_colorpicker_margin_layout"
android:layout_marginEnd="@dimen/dialog_colorpicker_margin_layout"
android:lines="1"
android:text="@android:string/cancel"
android:textSize="@dimen/dialog_colorpicker_textsize_button"
@ -55,7 +55,6 @@
android:id="@+id/dialog_colorpicker_ok"
android:layout_width="wrap_content"
android:layout_height="@dimen/dialog_colorpicker_height_button"
android:layout_margin="@dimen/dialog_colorpicker_margin_layout"
android:lines="1"
android:text="@android:string/ok"
android:textSize="@dimen/dialog_colorpicker_textsize_button"

View File

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/CardView">
style="@style/CardViewStyle">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/item_announcement_container"

View File

@ -57,20 +57,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/page_instance_announcement_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/instance_announcement_label"
android:gravity="center"
android:lines="1"
android:textSize="@dimen/page_instance_textsize_label_announcement"
android:layout_margin="@dimen/page_instance_margin_views"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/page_instance_list_fragment"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/page_instance_list_fragment"
android:layout_width="match_parent"
@ -78,7 +64,7 @@
android:layout_weight="1"
android:name="org.nuclearfog.twidda.ui.fragments.AnnouncementFragment"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/page_instance_announcement_header"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

View File

@ -12,6 +12,6 @@
android:id="@+id/menu_instance_show_all_announcements"
android:title="@string/menu_instance_show_all"
android:checkable="true"
app:showAsAction="never"/>
app:showAsAction="never" />
</menu>

View File

@ -368,7 +368,7 @@
<string name="error_api_error">API Fehler</string>
<string name="menu_status_history">Bearbeitungsverlauf</string>
<string name="hint_duration">Dauer</string>
<string name="instance_announcement_label">Ankündigungen</string>
<string name="announcement_dismiss">Instanz-Ankündigung loschen</string>
<string name="confirm_dismiss_announcement">verstecke Instanz-Benachrichtigung</string>
<string name="description_announcement_reaction">Reaktionen einer Ankündigung</string>
</resources>

View File

@ -328,7 +328,7 @@
<dimen name="item_filter_button_size">20sp</dimen>
<!--dimens of item_announcement.xml-->
<dimen name="item_announcement_card_padding">8dp</dimen>
<dimen name="item_announcement_card_padding">5dp</dimen>
<dimen name="item_announcement_view_margin">5dp</dimen>
<dimen name="item_announcement_textsize_content">14sp</dimen>
<dimen name="item_announcement_textsize_time">12sp</dimen>
@ -337,9 +337,7 @@
<!--dimens of page_instance.xml-->
<dimen name="page_instance_toolbar_height">@dimen/toolbar_height</dimen>
<dimen name="page_instance_textsize_label_announcement">16sp</dimen>
<dimen name="page_instance_textsize_description">14sp</dimen>
<dimen name="page_instance_margin_views">5dp</dimen>
<dimen name="page_instance_padding_description">5dp</dimen>
<!--dimens of dialog_push.xml-->

View File

@ -392,5 +392,4 @@
<string name="dialog_filter_title_keywords">Words to exclude</string>
<string name="dialog_filter_edit_hint_exclude">word anotherword\n\"whole word\"</string>
<string name="hint_duration">Duration</string>
<string name="instance_announcement_label">Announcements</string>
</resources>