From 3f27fa356e5445666f8e5a811a29449c66e1dbc7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E2=80=98acehuang310=E2=80=99?= <‘1623330381@qq.com’>
Date: Wed, 3 Jan 2024 11:31:04 +0800
Subject: [PATCH 1/5] add tag
---
.idea/.gitignore | 3 +
.idea/compiler.xml | 2 +-
.idea/deploymentTargetDropDown.xml | 17 +
.idea/gradle.xml | 2 +-
.idea/jarRepositories.xml | 25 +-
.idea/misc.xml | 47 +--
.idea/vcs.xml | 2 +-
.../ActivityDiaryApplication.java | 3 +-
.../activitydiary/model/DiaryActivity.java | 17 +-
.../model/conditions/SPUtils.java | 346 ++++++++++++++++++
.../ui/generic/EditActivity.java | 14 +-
.../ui/main/SelectRecyclerViewAdapter.java | 3 +
.../ui/main/SelectViewHolders.java | 3 +-
.../main/res/layout/activity_edit_content.xml | 8 +-
.../main/res/layout/select_recycler_item.xml | 13 +-
app/src/main/res/values/strings.xml | 2 +
16 files changed, 432 insertions(+), 75 deletions(-)
create mode 100644 .idea/.gitignore
create mode 100644 .idea/deploymentTargetDropDown.xml
create mode 100644 app/src/main/java/de/rampro/activitydiary/model/conditions/SPUtils.java
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 000000000..26d33521a
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index fb7f4a8a4..b589d56e9 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
new file mode 100644
index 000000000..28c203618
--- /dev/null
+++ b/.idea/deploymentTargetDropDown.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index a2d7c2133..6d8905056 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -1,12 +1,12 @@
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 70ed5232b..0ad17cbd3 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,50 +1,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 94a25f7f4..6c0b86358 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/java/de/rampro/activitydiary/ActivityDiaryApplication.java b/app/src/main/java/de/rampro/activitydiary/ActivityDiaryApplication.java
index 2de7ac12a..8c9666832 100644
--- a/app/src/main/java/de/rampro/activitydiary/ActivityDiaryApplication.java
+++ b/app/src/main/java/de/rampro/activitydiary/ActivityDiaryApplication.java
@@ -29,6 +29,7 @@
import org.acra.data.StringFormat;
import de.rampro.activitydiary.helpers.GraphicsHelper;
+import de.rampro.activitydiary.model.conditions.SPUtils;
public class ActivityDiaryApplication extends Application {
@@ -37,7 +38,7 @@ public class ActivityDiaryApplication extends Application {
public void onCreate() {
super.onCreate();
ActivityDiaryApplication.context = getApplicationContext();
-
+ SPUtils.init(this);
/* now do some init stuff */
String colors[] = context.getResources().getStringArray(R.array.activityColorPalette);
diff --git a/app/src/main/java/de/rampro/activitydiary/model/DiaryActivity.java b/app/src/main/java/de/rampro/activitydiary/model/DiaryActivity.java
index 057127fbc..4c3d9986e 100644
--- a/app/src/main/java/de/rampro/activitydiary/model/DiaryActivity.java
+++ b/app/src/main/java/de/rampro/activitydiary/model/DiaryActivity.java
@@ -23,11 +23,18 @@ public class DiaryActivity{
private String mName;
private int mId;
private int mColor;
-
+ private String mTag;
public DiaryActivity(int id, String name, int color){
mId = id;
mName = name;
mColor = color;
+
+ }
+ public DiaryActivity(int id, String name, int color,String tag){
+ mId = id;
+ mName = name;
+ mColor = color;
+ mTag=tag;
}
public String getName(){
@@ -56,4 +63,12 @@ public String toString(){
public int hashCode(){
return mId;
}
+
+ public String getmTag() {
+ return mTag;
+ }
+
+ public void setmTag(String mTag) {
+ this.mTag = mTag;
+ }
}
diff --git a/app/src/main/java/de/rampro/activitydiary/model/conditions/SPUtils.java b/app/src/main/java/de/rampro/activitydiary/model/conditions/SPUtils.java
new file mode 100644
index 000000000..b42f2878f
--- /dev/null
+++ b/app/src/main/java/de/rampro/activitydiary/model/conditions/SPUtils.java
@@ -0,0 +1,346 @@
+package de.rampro.activitydiary.model.conditions;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Build;
+
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * must call init at your application level or equiv, before you use any other methods
+ */
+public class SPUtils {
+
+ private static SharedPreferences sharedPreferences;
+ private static SPUtils prefsInstance;
+
+ private static final String preferencesName = "preferences";
+ private static final String LENGTH = "_length";
+
+ private static final String DEFAULT_STRING_VALUE = "";
+ private static final int DEFAULT_INT_VALUE = -1;
+ private static final double DEFAULT_DOUBLE_VALUE = -1d;
+ private static final float DEFAULT_FLOAT_VALUE = -1f;
+ private static final long DEFAULT_LONG_VALUE = -1L;
+ private static final boolean DEFAULT_BOOLEAN_VALUE = false;
+
+ private SPUtils(Context context) {
+ if (sharedPreferences == null) {
+ sharedPreferences = context.getApplicationContext().getSharedPreferences(
+ preferencesName,
+ Context.MODE_PRIVATE
+ );
+ }
+ }
+
+ /**
+ * @param context
+ * @return Returns a 'Prefs' instance
+ */
+ public static SPUtils init(Context context) {
+ if (prefsInstance == null) {
+ prefsInstance = new SPUtils(context);
+ }
+ return prefsInstance;
+ }
+
+ // String related methods
+
+ /**
+ * @param what
+ * @return Returns the stored value of 'what'
+ */
+ public static String getString(String what) {
+ return sharedPreferences.getString(what, DEFAULT_STRING_VALUE);
+ }
+
+ /**
+ * @param what
+ * @param defaultString
+ * @return Returns the stored value of 'what'
+ */
+ public static String getString(String what, String defaultString) {
+ return sharedPreferences.getString(what, defaultString);
+ }
+
+ /**
+ * @param where
+ * @param what
+ */
+ public static void putString(String where, String what) {
+ sharedPreferences.edit().putString(where, what).apply();
+ }
+
+ // int related methods
+
+ /**
+ * @param what
+ * @return Returns the stored value of 'what'
+ */
+ public static int getInt(String what) {
+ int result=sharedPreferences.getInt(what, DEFAULT_INT_VALUE);
+ if (result==-1){
+ return 0;
+ }else
+ return result;
+ }
+
+ /**
+ * @param what
+ * @param defaultInt
+ * @return Returns the stored value of 'what'
+ */
+ public static int getInt(String what, int defaultInt) {
+ return sharedPreferences.getInt(what, defaultInt);
+ }
+
+ /**
+ * @param where
+ * @param what
+ */
+ public static void putInt(String where, int what) {
+ sharedPreferences.edit().putInt(where, what).apply();
+ }
+
+ // double related methods
+
+ /**
+ * @param what
+ * @return Returns the stored value of 'what'
+ */
+ public static double getDouble(String what) {
+ if (!contains(what))
+ return DEFAULT_DOUBLE_VALUE;
+ return Double.longBitsToDouble(getLong(what));
+ }
+
+ /**
+ * @param what
+ * @param defaultDouble
+ * @return Returns the stored value of 'what'
+ */
+ public double getDouble(String what, double defaultDouble) {
+ if (!contains(what))
+ return defaultDouble;
+ return Double.longBitsToDouble(getLong(what));
+ }
+
+ /**
+ * @param where
+ * @param what
+ */
+ public void putDouble(String where, double what) {
+ putLong(where, Double.doubleToRawLongBits(what));
+ }
+
+ // float related methods
+
+ /**
+ * @param what
+ * @return Returns the stored value of 'what'
+ */
+ public float getFloat(String what) {
+ return sharedPreferences.getFloat(what, DEFAULT_FLOAT_VALUE);
+ }
+
+ /**
+ * @param what
+ * @param defaultFloat
+ * @return Returns the stored value of 'what'
+ */
+ public static float getFloat(String what, float defaultFloat) {
+ return sharedPreferences.getFloat(what, defaultFloat);
+ }
+
+ /**
+ * @param where
+ * @param what
+ */
+ public static void putFloat(String where, float what) {
+ sharedPreferences.edit().putFloat(where, what).apply();
+ }
+
+ // long related methods
+
+ /**
+ * @param what
+ * @return Returns the stored value of 'what'
+ */
+ public static long getLong(String what) {
+ return sharedPreferences.getLong(what, DEFAULT_LONG_VALUE);
+ }
+
+ /**
+ * @param what
+ * @param defaultLong
+ * @return Returns the stored value of 'what'
+ */
+ public static long getLong(String what, long defaultLong) {
+ return sharedPreferences.getLong(what, defaultLong);
+ }
+
+ /**
+ * @param where
+ * @param what
+ */
+ public static void putLong(String where, long what) {
+ sharedPreferences.edit().putLong(where, what).apply();
+ }
+
+ public static float getFloat(String what, long defaultLong) {
+ return sharedPreferences.getFloat(what, defaultLong);
+ }
+
+ /**
+ * @param where
+ * @param what
+ */
+ public static void putFloat(String where, long what) {
+ sharedPreferences.edit().putFloat(where, what).apply();
+ }
+
+ // boolean related methods
+
+ /**
+ * @param what
+ * @return Returns the stored value of 'what'
+ */
+ public static boolean getBoolean(String what) {
+ return sharedPreferences.getBoolean(what, DEFAULT_BOOLEAN_VALUE);
+ }
+
+ /**
+ * @param what
+ * @param defaultBoolean
+ * @return Returns the stored value of 'what'
+ */
+ public static boolean getBoolean(String what, boolean defaultBoolean) {
+ return sharedPreferences.getBoolean(what, defaultBoolean);
+ }
+
+ /**
+ * @param where
+ * @param what
+ */
+ public static void putBoolean(String where, boolean what) {
+ sharedPreferences.edit().putBoolean(where, what).apply();
+ }
+
+ // String set methods
+
+ /**
+ * @param key
+ * @param value
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public static void putStringSet(final String key, final Set value) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ sharedPreferences.edit().putStringSet(key, value).apply();
+ } else {
+ // Workaround for pre-HC's lack of StringSets
+ putOrderedStringSet(key, value);
+ }
+ }
+
+ public static Set getStringSet(final String key) {
+ return sharedPreferences.getStringSet(key,new HashSet());
+ }
+
+ /**
+ * @param key
+ * @param value
+ */
+ public static void putOrderedStringSet(String key, Set value) {
+ int stringSetLength = 0;
+ if (sharedPreferences.contains(key + LENGTH)) {
+ // First getString what the value was
+ stringSetLength = getInt(key + LENGTH);
+ }
+ putInt(key + LENGTH, value.size());
+ int i = 0;
+ for (String aValue : value) {
+ putString(key + "[" + i + "]", aValue);
+ i++;
+ }
+ for (; i < stringSetLength; i++) {
+ // Remove any remaining values
+ remove(key + "[" + i + "]");
+ }
+ }
+
+ /**
+ * @param key
+ * @param defValue
+ * @return Returns the String Set with HoneyComb compatibility
+ */
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public Set getStringSet(final String key, final Set defValue) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ return sharedPreferences.getStringSet(key, defValue);
+ } else {
+ // Workaround for pre-HC's missing getStringSet
+ return getOrderedStringSet(key, defValue);
+ }
+ }
+
+ /**
+ * @param key
+ * @param defValue
+ * @return Returns the ordered String Set
+ */
+ public Set getOrderedStringSet(String key, final Set defValue) {
+ if (contains(key + LENGTH)) {
+ LinkedHashSet set = new LinkedHashSet();
+ int stringSetLength = getInt(key + LENGTH);
+ if (stringSetLength >= 0) {
+ for (int i = 0; i < stringSetLength; i++) {
+ set.add(getString(key + "[" + i + "]"));
+ }
+ }
+ return set;
+ }
+ return defValue;
+ }
+
+ // end related methods
+
+ /**
+ * @param key
+ */
+ public static void remove(final String key) {
+ if (contains(key + LENGTH)) {
+ // Workaround for pre-HC's lack of StringSets
+ int stringSetLength = getInt(key + LENGTH);
+ if (stringSetLength >= 0) {
+ sharedPreferences.edit().remove(key + LENGTH).apply();
+ for (int i = 0; i < stringSetLength; i++) {
+ sharedPreferences.edit().remove(key + "[" + i + "]").apply();
+ }
+ }
+ }
+ sharedPreferences.edit().remove(key);
+ }
+
+ /**
+ * @param key
+ * @return Returns if that key exists
+ */
+ public static boolean contains(final String key) {
+ return sharedPreferences.contains(key);
+ }
+
+ /**
+ * Clear all the preferences
+ */
+ public static void clear() {
+ sharedPreferences.edit().clear().apply();
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/de/rampro/activitydiary/ui/generic/EditActivity.java b/app/src/main/java/de/rampro/activitydiary/ui/generic/EditActivity.java
index 53ea4499a..c827c6740 100644
--- a/app/src/main/java/de/rampro/activitydiary/ui/generic/EditActivity.java
+++ b/app/src/main/java/de/rampro/activitydiary/ui/generic/EditActivity.java
@@ -55,6 +55,7 @@
import de.rampro.activitydiary.helpers.JaroWinkler;
import de.rampro.activitydiary.helpers.GraphicsHelper;
import de.rampro.activitydiary.model.DiaryActivity;
+import de.rampro.activitydiary.model.conditions.SPUtils;
/*
* EditActivity to add and modify activities
@@ -73,8 +74,9 @@ public class EditActivity extends BaseActivity implements ActivityHelper.DataCha
private final String COLOR_KEY = "COLOR";
private final String NAME_KEY = "NAME";
+ private final String TAG_KEY = "TAG";
- private EditText mActivityName;
+ private EditText mActivityName,mActivityTag;
private TextInputLayout mActivityNameTIL;
private ImageView mActivityColorImg;
private int mActivityColor;
@@ -281,6 +283,8 @@ private void setBtnTooltip(View view, @Nullable CharSequence tooltipText) {
private void refreshElements() {
if (currentActivity != null) {
mActivityName.setText(currentActivity.getName());
+ mActivityTag.setText(currentActivity.getmTag());
+
getSupportActionBar().setTitle(currentActivity.getName());
mActivityColor = currentActivity.getColor();
} else {
@@ -317,6 +321,7 @@ protected void onCreate(Bundle savedInstanceState) {
setContent(contentView);
mActivityName = (EditText) contentView.findViewById(R.id.edit_activity_name);
+ mActivityTag = (EditText) contentView.findViewById(R.id.edit_activity_tag);
mActivityName.addTextChangedListener(new TextWatcher(){
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
@@ -387,6 +392,7 @@ public void onPause() {
public void onSaveInstanceState(Bundle outState) {
outState.putString(NAME_KEY, mActivityName.getText().toString());
outState.putInt(COLOR_KEY, mActivityColor);
+ outState.putString(TAG_KEY, mActivityTag.getText().toString());
// call superclass to save any view hierarchy
super.onSaveInstanceState(outState);
}
@@ -417,9 +423,13 @@ public boolean onOptionsItemSelected(MenuItem item) {
).show();
} else {
if (currentActivity == null) {
- ActivityHelper.helper.insertActivity(new DiaryActivity(-1, mActivityName.getText().toString(), mActivityColor));
+ ActivityHelper.helper.insertActivity(new DiaryActivity(-1, mActivityName.getText().toString(), mActivityColor,mActivityTag.getText().toString()));
+ SPUtils.putString(mActivityName.getText().toString()+mActivityColor,mActivityTag.getText().toString());
} else {
currentActivity.setName(mActivityName.getText().toString());
+ currentActivity.setmTag(mActivityTag.getText().toString());
+ SPUtils.putString(mActivityName.getText().toString()+mActivityColor,mActivityTag.getText().toString());
+
currentActivity.setColor(mActivityColor);
ActivityHelper.helper.updateActivity(currentActivity);
}
diff --git a/app/src/main/java/de/rampro/activitydiary/ui/main/SelectRecyclerViewAdapter.java b/app/src/main/java/de/rampro/activitydiary/ui/main/SelectRecyclerViewAdapter.java
index 60dae75b9..27dfb9a66 100644
--- a/app/src/main/java/de/rampro/activitydiary/ui/main/SelectRecyclerViewAdapter.java
+++ b/app/src/main/java/de/rampro/activitydiary/ui/main/SelectRecyclerViewAdapter.java
@@ -31,6 +31,7 @@
import de.rampro.activitydiary.R;
import de.rampro.activitydiary.helpers.GraphicsHelper;
import de.rampro.activitydiary.model.DiaryActivity;
+import de.rampro.activitydiary.model.conditions.SPUtils;
public class SelectRecyclerViewAdapter extends RecyclerView.Adapter{
private List mActivityList;
@@ -55,11 +56,13 @@ public SelectViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
public void onBindViewHolder(SelectViewHolders holder, int position) {
DiaryActivity act = mActivityList.get(position);
NumberFormat formatter = new DecimalFormat("#0.00");
+ holder.mTag.setText("Tag:"+ SPUtils.getString(act.getName()+act.getColor()));
holder.mName.setText(act.getName());
// show likelyhood in activity name
// holder.mName.setText(act.getName() + " (" + formatter.format(ActivityHelper.helper.likelihoodFor(act)) + ")");
// TODO #33: holder.mSymbol.setImageResource(act.getPhoto());
holder.mBackground.setBackgroundColor(act.getColor());
+
holder.mName.setTextColor(GraphicsHelper.textColorOnBackground(act.getColor()));
// TODO #31: set the width based on the likelyhood
diff --git a/app/src/main/java/de/rampro/activitydiary/ui/main/SelectViewHolders.java b/app/src/main/java/de/rampro/activitydiary/ui/main/SelectViewHolders.java
index b95aa5272..4c864aca4 100644
--- a/app/src/main/java/de/rampro/activitydiary/ui/main/SelectViewHolders.java
+++ b/app/src/main/java/de/rampro/activitydiary/ui/main/SelectViewHolders.java
@@ -28,7 +28,7 @@
class SelectViewHolders extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
- public TextView mName;
+ public TextView mName,mTag;
public ImageView mSymbol;
public View mBackground;
private SelectRecyclerViewAdapter.SelectListener mListener;
@@ -37,6 +37,7 @@ public SelectViewHolders(SelectRecyclerViewAdapter.SelectListener listener, View
super(itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
+ mTag= (TextView) itemView.findViewById(R.id.tv_tag);
mName = (TextView) itemView.findViewById(R.id.activity_name);
mSymbol = (ImageView) itemView.findViewById(R.id.activity_image);
mBackground = (View) itemView.findViewById(R.id.activity_background);
diff --git a/app/src/main/res/layout/activity_edit_content.xml b/app/src/main/res/layout/activity_edit_content.xml
index 88e09cff8..0ce189b0f 100644
--- a/app/src/main/res/layout/activity_edit_content.xml
+++ b/app/src/main/res/layout/activity_edit_content.xml
@@ -24,7 +24,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp">
-
+
-
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 39608e922..68facca1f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -74,6 +74,8 @@
Activity color
Activity title
+ Activity tag
+
Choose current activity…
@string/dialog_title_note
From ea7ec9e180b3fbcabd45330652a7e009bc3de562 Mon Sep 17 00:00:00 2001
From: Cheng Tan
Date: Wed, 3 Jan 2024 12:41:43 +0800
Subject: [PATCH 2/5] Dependency introduced.
---
.idea/deploymentTargetDropDown.xml | 17 +++++------------
.idea/gradle.xml | 6 +++---
.idea/migrations.xml | 10 ++++++++++
.idea/misc.xml | 1 -
.idea/modules.xml | 12 ------------
.idea/vcs.xml | 2 +-
app/build.gradle | 1 +
build.gradle | 2 ++
8 files changed, 22 insertions(+), 29 deletions(-)
create mode 100644 .idea/migrations.xml
delete mode 100644 .idea/modules.xml
diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
index 28c203618..0c0c33838 100644
--- a/.idea/deploymentTargetDropDown.xml
+++ b/.idea/deploymentTargetDropDown.xml
@@ -1,17 +1,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 6d8905056..0897082f7 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -1,18 +1,18 @@
+
-
-
-
+
+
diff --git a/.idea/migrations.xml b/.idea/migrations.xml
new file mode 100644
index 000000000..f8051a6f9
--- /dev/null
+++ b/.idea/migrations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 0ad17cbd3..8978d23db 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,3 @@
-
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100644
index 927cc2ecc..000000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 6c0b86358..94a25f7f4 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 23cabf362..d8a0c6df8 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -125,6 +125,7 @@ dependencies {
implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
implementation 'androidx.exifinterface:exifinterface:1.3.3'
implementation 'com.pes.materialcolorpicker:library:1.2.2'
+ implementation 'com.github.widemouth-dz:wmrichtexteditor:2.0.4'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation "androidx.lifecycle:lifecycle-viewmodel:2.5.1"
diff --git a/build.gradle b/build.gradle
index d91b869d2..9185facce 100644
--- a/build.gradle
+++ b/build.gradle
@@ -23,6 +23,7 @@ buildscript {
repositories {
google()
mavenCentral()
+ maven { url 'https://jitpack.io' }
if (project.file('ActivityDiarySigning.properties').exists()) {
mavenCentral()
}
@@ -46,6 +47,7 @@ allprojects {
repositories {
google()
mavenCentral()
+ maven { url 'https://jitpack.io' }
jcenter()
maven { url "https://jitpack.io" }
}
From 828170d17eae2d72cbef6e8aa4820210d7e39b9f Mon Sep 17 00:00:00 2001
From: Cheng Tan
Date: Wed, 3 Jan 2024 14:42:40 +0800
Subject: [PATCH 3/5] Rich Text Editor Intro.
---
.../activitydiary/ui/main/NoteEditDialog.java | 95 +++++++++++++++++--
.../main/res/layout/dialog_note_editor.xml | 46 ++++-----
2 files changed, 102 insertions(+), 39 deletions(-)
diff --git a/app/src/main/java/de/rampro/activitydiary/ui/main/NoteEditDialog.java b/app/src/main/java/de/rampro/activitydiary/ui/main/NoteEditDialog.java
index 5a9964964..87fa6a248 100644
--- a/app/src/main/java/de/rampro/activitydiary/ui/main/NoteEditDialog.java
+++ b/app/src/main/java/de/rampro/activitydiary/ui/main/NoteEditDialog.java
@@ -32,7 +32,41 @@
import de.rampro.activitydiary.R;
+import com.widemouth.library.toolitem.WMToolAlignment;
+import com.widemouth.library.toolitem.WMToolBackgroundColor;
+import com.widemouth.library.toolitem.WMToolBold;
+import com.widemouth.library.toolitem.WMToolImage;
+import com.widemouth.library.toolitem.WMToolItalic;
+import com.widemouth.library.toolitem.WMToolItem;
+import com.widemouth.library.toolitem.WMToolListBullet;
+import com.widemouth.library.toolitem.WMToolListClickToSwitch;
+import com.widemouth.library.toolitem.WMToolListNumber;
+import com.widemouth.library.toolitem.WMToolQuote;
+import com.widemouth.library.toolitem.WMToolSplitLine;
+import com.widemouth.library.toolitem.WMToolStrikethrough;
+import com.widemouth.library.toolitem.WMToolTextColor;
+import com.widemouth.library.toolitem.WMToolTextSize;
+import com.widemouth.library.toolitem.WMToolUnderline;
+import com.widemouth.library.wmview.WMEditText;
+import com.widemouth.library.wmview.WMToolContainer;
+
public class NoteEditDialog extends DialogFragment {
+ private WMEditText editText;
+ private WMToolContainer toolContainer;
+ private WMToolItem toolBold = new WMToolBold();
+ private WMToolItem toolItalic = new WMToolItalic();
+ private WMToolItem toolUnderline = new WMToolUnderline();
+ private WMToolItem toolStrikethrough = new WMToolStrikethrough();
+ private WMToolItem toolImage = new WMToolImage();
+ private WMToolItem toolTextColor = new WMToolTextColor();
+ private WMToolItem toolBackgroundColor = new WMToolBackgroundColor();
+ private WMToolItem toolTextSize = new WMToolTextSize();
+ private WMToolItem toolListNumber = new WMToolListNumber();
+ private WMToolItem toolListBullet = new WMToolListBullet();
+ private WMToolItem toolAlignment = new WMToolAlignment();
+ private WMToolItem toolQuote = new WMToolQuote();
+ private WMToolItem toolListClickToSwitch = new WMToolListClickToSwitch();
+ private WMToolItem toolSplitLine = new WMToolSplitLine();
private String note;
private EditText input;
private NoteEditDialogListener mListener;
@@ -45,27 +79,32 @@ public interface NoteEditDialogListener {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
+
Dialog result;
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-
LayoutInflater inflater = getActivity().getLayoutInflater();
-
builder.setTitle(R.string.dialog_title_note);
View dlgView = inflater.inflate(R.layout.dialog_note_editor, null);
- input = (EditText) dlgView.findViewById(R.id.noteText);
- if(savedInstanceState != null){
- input.setText(savedInstanceState.getString("Note"));
- }else{
- input.setText(note);
- }
- input.setSelection(input.getText().length());
+ editText = (WMEditText) dlgView.findViewById(R.id.WMEditText);
+ toolContainer = (WMToolContainer) dlgView.findViewById(R.id.WMToolContainer);
+
+ // input = (EditText) dlgView.findViewById(R.id.noteText);
+ // if(savedInstanceState != null){
+ // input.setText(savedInstanceState.getString("Note"));
+ // }else{
+ // input.setText(note);
+ // }
+
+ // input.setSelection(input.getText().length());
+
builder.setView(dlgView)
// Add action buttons
+
.setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
- mListener.onNoteEditPositiveClock(input.getText().toString(), NoteEditDialog.this);
+ mListener.onNoteEditPositiveClock("succ", NoteEditDialog.this);
}
})
.setNegativeButton(R.string.dlg_cancel, new DialogInterface.OnClickListener() {
@@ -112,4 +151,40 @@ public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("Note", input.getText().toString());
}
+
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ toolBold = new WMToolBold();
+ toolItalic = new WMToolItalic();
+ toolUnderline = new WMToolUnderline();
+ toolStrikethrough = new WMToolStrikethrough();
+ toolImage = new WMToolImage();
+ toolTextColor = new WMToolTextColor();
+ toolBackgroundColor = new WMToolBackgroundColor();
+ toolTextSize = new WMToolTextSize();
+ toolListNumber = new WMToolListNumber();
+ toolListBullet = new WMToolListBullet();
+ toolAlignment = new WMToolAlignment();
+ toolQuote = new WMToolQuote();
+ toolListClickToSwitch = new WMToolListClickToSwitch();
+ toolSplitLine = new WMToolSplitLine();
+
+ toolContainer.addToolItem(toolImage);
+ toolContainer.addToolItem(toolTextColor);
+ toolContainer.addToolItem(toolBackgroundColor);
+ toolContainer.addToolItem(toolTextSize);
+ toolContainer.addToolItem(toolBold);
+ toolContainer.addToolItem(toolItalic);
+ toolContainer.addToolItem(toolUnderline);
+ toolContainer.addToolItem(toolStrikethrough);
+ toolContainer.addToolItem(toolListNumber);
+ toolContainer.addToolItem(toolListBullet);
+ toolContainer.addToolItem(toolAlignment);
+ toolContainer.addToolItem(toolQuote);
+ toolContainer.addToolItem(toolListClickToSwitch);
+ toolContainer.addToolItem(toolSplitLine);
+ editText.setupWithToolContainer(toolContainer);
+ }
}
diff --git a/app/src/main/res/layout/dialog_note_editor.xml b/app/src/main/res/layout/dialog_note_editor.xml
index 85607578e..0173a4e66 100644
--- a/app/src/main/res/layout/dialog_note_editor.xml
+++ b/app/src/main/res/layout/dialog_note_editor.xml
@@ -1,34 +1,22 @@
-
-
-
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+
-
+ android:layout_height="0dp"
+ android:layout_weight="1">
+
+
-
\ No newline at end of file
+
\ No newline at end of file
From 545e624654962bc55bd0db1ce5dfd522f503a956 Mon Sep 17 00:00:00 2001
From: Cheng Tan
Date: Wed, 3 Jan 2024 15:44:52 +0800
Subject: [PATCH 4/5] Bug fixed.
---
.../activitydiary/ui/main/MainActivity.java | 2 ++
.../activitydiary/ui/main/NoteEditDialog.java | 22 ++++++++-----------
2 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/app/src/main/java/de/rampro/activitydiary/ui/main/MainActivity.java b/app/src/main/java/de/rampro/activitydiary/ui/main/MainActivity.java
index 3e6d5469d..6fea54407 100644
--- a/app/src/main/java/de/rampro/activitydiary/ui/main/MainActivity.java
+++ b/app/src/main/java/de/rampro/activitydiary/ui/main/MainActivity.java
@@ -50,6 +50,8 @@
import androidx.recyclerview.widget.RecyclerView;
import androidx.appcompat.widget.SearchView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
+
+import android.text.Html;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.format.DateFormat;
diff --git a/app/src/main/java/de/rampro/activitydiary/ui/main/NoteEditDialog.java b/app/src/main/java/de/rampro/activitydiary/ui/main/NoteEditDialog.java
index 87fa6a248..e3fd2de5c 100644
--- a/app/src/main/java/de/rampro/activitydiary/ui/main/NoteEditDialog.java
+++ b/app/src/main/java/de/rampro/activitydiary/ui/main/NoteEditDialog.java
@@ -25,6 +25,8 @@
import android.os.Bundle;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AlertDialog;
+
+import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
@@ -89,22 +91,15 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {
editText = (WMEditText) dlgView.findViewById(R.id.WMEditText);
toolContainer = (WMToolContainer) dlgView.findViewById(R.id.WMToolContainer);
- // input = (EditText) dlgView.findViewById(R.id.noteText);
- // if(savedInstanceState != null){
- // input.setText(savedInstanceState.getString("Note"));
- // }else{
- // input.setText(note);
- // }
-
- // input.setSelection(input.getText().length());
-
builder.setView(dlgView)
// Add action buttons
.setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
- mListener.onNoteEditPositiveClock("succ", NoteEditDialog.this);
+ note = editText.getHtml();
+ System.out.println(note);
+ mListener.onNoteEditPositiveClock(note, NoteEditDialog.this);
}
})
.setNegativeButton(R.string.dlg_cancel, new DialogInterface.OnClickListener() {
@@ -131,9 +126,10 @@ public void onAttach(Context context) {
}
}
- public void setText(String text){
- if(input != null){
- input.setText(text);
+ public void setText(String text) {
+ System.out.println("setText, text: " + text);
+ if(input != null) {
+ input.setText(Html.fromHtml(text));
}
note = text;
}
From df239faea5e8c02bae97022529fd06439833b50a Mon Sep 17 00:00:00 2001
From: jiangxiansheng <1874813131@qq.com>
Date: Wed, 3 Jan 2024 22:06:00 +0800
Subject: [PATCH 5/5] part3
---
.idea/gradle.xml | 3 +-
app/src/main/AndroidManifest.xml | 2 +
.../activitydiary/ui/main/MainActivity.java | 29 ++-
.../ui/main/RedPacketActivity.java | 215 ++++++++++++++++++
app/src/main/res/color/btn_color_selector.xml | 24 ++
app/src/main/res/drawable/btn_selector.xml | 26 +++
.../main/res/drawable/close_red_packet.xml | 5 +
.../main/res/drawable/close_text_on_video.xml | 5 +
.../main/res/drawable/red_packet_image.png | Bin 0 -> 477220 bytes
.../main/res/layout/activity_main_content.xml | 65 ++++--
app/src/main/res/layout/red_packet_video.xml | 136 +++++++++++
11 files changed, 490 insertions(+), 20 deletions(-)
create mode 100644 app/src/main/java/de/rampro/activitydiary/ui/main/RedPacketActivity.java
create mode 100644 app/src/main/res/color/btn_color_selector.xml
create mode 100644 app/src/main/res/drawable/btn_selector.xml
create mode 100644 app/src/main/res/drawable/close_red_packet.xml
create mode 100644 app/src/main/res/drawable/close_text_on_video.xml
create mode 100644 app/src/main/res/drawable/red_packet_image.png
create mode 100644 app/src/main/res/layout/red_packet_video.xml
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 0897082f7..9f47dfb43 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -4,8 +4,9 @@
+
-
+
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0ea4fc185..f9c53416e 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -61,6 +61,8 @@
+
{
// Handle the click on the FAB
@@ -414,7 +441,7 @@ public void onActivityChanged(){
ActivityDiaryContract.DiaryActivity.X_START_OF_LAST
},
ActivityDiaryContract.DiaryActivity._DELETED + " = 0 AND "
- + ActivityDiaryContract.DiaryActivity._ID + " = ?",
+ + ActivityDiaryContract.DiaryActivity._ID + " = ?",
new String[] {
Integer.toString(newAct.getId())
},
diff --git a/app/src/main/java/de/rampro/activitydiary/ui/main/RedPacketActivity.java b/app/src/main/java/de/rampro/activitydiary/ui/main/RedPacketActivity.java
new file mode 100644
index 000000000..9fa890429
--- /dev/null
+++ b/app/src/main/java/de/rampro/activitydiary/ui/main/RedPacketActivity.java
@@ -0,0 +1,215 @@
+/*
+ * ActivityDiary
+ *
+ * Copyright (C) 2024 Raphael Mack http://www.raphael-mack.de
+ *
+ * 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 de.rampro.activitydiary.ui.main;
+
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.os.Bundle;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.widget.Button;
+import android.widget.MediaController;
+
+import java.io.IOException;
+
+import de.rampro.activitydiary.R;
+import de.rampro.activitydiary.ui.generic.BaseActivity;
+
+
+public class RedPacketActivity extends BaseActivity implements
+ MediaController.MediaPlayerControl,
+ MediaPlayer.OnBufferingUpdateListener,
+ SurfaceHolder.Callback{
+ private MediaPlayer mediaPlayer;
+ private MediaController controller;
+ private Button closeTextOnVideo;
+ private Button btnUnderVideo;
+ private int bufferPercentage = 0;
+ @SuppressLint("MissingInflatedId")
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.red_packet_video);
+ mediaPlayer = new MediaPlayer();
+ controller = new MediaController(this);
+ controller.setAnchorView(findViewById(R.id.root_ll));
+ initSurfaceView();
+
+ start();
+
+ closeTextOnVideo = (Button) findViewById(R.id.close_text_on_video);
+ btnUnderVideo = (Button) findViewById(R.id.button_under_video);
+ closeTextOnVideo.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(RedPacketActivity.this, MainActivity.class);
+ // 启动目标Activity
+ startActivity(intent);
+ }
+ });
+ btnUnderVideo.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ start();
+ }
+ });
+
+ }
+
+ private void initSurfaceView() {
+ SurfaceView videoSuf = (SurfaceView) findViewById(R.id.controll_surfaceView);
+ videoSuf.setZOrderOnTop(false);
+ videoSuf.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+ videoSuf.getHolder().addCallback(this);
+ }
+ @Override
+ protected void onResume() {
+ super.onResume();
+ try {
+ String path = "https://poss-videocloud.cns.com.cn/oss/2021/05/08/chinanews/MEIZI_YUNSHI/onair/25AFA3CA2F394DB38420CC0A44483E82.mp4" ;
+ mediaPlayer.setDataSource(path);
+ mediaPlayer.setOnBufferingUpdateListener(this);
+ //mediaPlayer.prepare();
+
+ controller.setMediaPlayer(this);
+ controller.setEnabled(true);
+
+ }catch (IOException e){
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mediaPlayer.isPlaying()){
+ mediaPlayer.stop();
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (null != mediaPlayer){
+ mediaPlayer.release();
+ mediaPlayer = null;
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ controller.show();
+ return super.onTouchEvent(event);
+ }
+
+ //MediaPlayer
+ @Override
+ public void onPointerCaptureChanged(boolean hasCapture) {
+
+ }
+ //MediaPlayerControl
+ @Override
+ public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
+ bufferPercentage = i;
+ }
+
+ @Override
+ public void start() {
+ if (null != mediaPlayer){
+ mediaPlayer.start();
+ }
+ }
+
+ @Override
+ public void pause() {
+ if (null != mediaPlayer){
+ mediaPlayer.pause();
+ }
+ }
+
+ @Override
+ public int getDuration() {
+ return mediaPlayer.getDuration();
+ }
+
+ @Override
+ public int getCurrentPosition() {
+ return mediaPlayer.getCurrentPosition();
+ }
+
+ @Override
+ public void seekTo(int i) {
+ mediaPlayer.seekTo(i);
+ }
+
+ @Override
+ public boolean isPlaying() {
+ if (mediaPlayer.isPlaying()){
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int getBufferPercentage() {
+ return bufferPercentage;
+ }
+
+ @Override
+ public boolean canPause() {
+ return true;
+ }
+
+ @Override
+ public boolean canSeekBackward() {
+ return true;
+ }
+
+ @Override
+ public boolean canSeekForward() {
+ return true;
+ }
+
+ @Override
+ public int getAudioSessionId() {
+ return 0;
+ }
+
+ //SurfaceHolder.callback
+ @Override
+ public void surfaceCreated(SurfaceHolder surfaceHolder) {
+ mediaPlayer.setDisplay(surfaceHolder);
+ mediaPlayer.prepareAsync();
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
+
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
+
+ }
+}
+
diff --git a/app/src/main/res/color/btn_color_selector.xml b/app/src/main/res/color/btn_color_selector.xml
new file mode 100644
index 000000000..722d371c2
--- /dev/null
+++ b/app/src/main/res/color/btn_color_selector.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/btn_selector.xml b/app/src/main/res/drawable/btn_selector.xml
new file mode 100644
index 000000000..6d4b45ac9
--- /dev/null
+++ b/app/src/main/res/drawable/btn_selector.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/close_red_packet.xml b/app/src/main/res/drawable/close_red_packet.xml
new file mode 100644
index 000000000..a0a94e3cc
--- /dev/null
+++ b/app/src/main/res/drawable/close_red_packet.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/close_text_on_video.xml b/app/src/main/res/drawable/close_text_on_video.xml
new file mode 100644
index 000000000..1b0b754f7
--- /dev/null
+++ b/app/src/main/res/drawable/close_text_on_video.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/red_packet_image.png b/app/src/main/res/drawable/red_packet_image.png
new file mode 100644
index 0000000000000000000000000000000000000000..eac45bbcfd047f58d0b83bf00043e6976f5c4d81
GIT binary patch
literal 477220
zcmagFcT`hp*FNkxIyxZgC;NDaM{5cqh0@Av-q$je&fWSz6J*17lD_ukia?dwDt8|rXz@Nt|v
zb&5;(sg~)fQ@@c?
zbGQ(2i&xbnhF@~X@6w1nzfPCxD03?awaQuv;bo`;Z=!KPpVErhTyd)RP2&Xuav7sa
zw_u@tnIbM#i(w}GhXdIVYg&li4<^kJFJ3>i3VGer5VjB>+g`Z|t)RVvljfRltzCyG
z2`bN;h=l`jhJD=dYHgM^(Cw+AHeIbz4fOTozq_X7VCj3}?%z}JTp
zL?o}-!sA99^k_(Kk}zv`5wOFrz#G=ej<21lyHQaGj1OJIU4Kusy>!%cAOxS!z74b-U3imXf7?|iq>eOp_B^4#}6=NOeG%d@t;=hEQ6BOg>
zcUB+#D{uIoDic{DY7H6eTIn_nT3cDwR&XD8Yg`p}kJwysKhQ}0q060uGRL?%id58o
z3RFYYD7>t(yS1)DFP&S#TIM=`0+%CVWb$4l%<1~mkyslbzP9mDirsPOaoCQpaq`Yp
z(W|ym&z;!IJ}TT9_1mF;`&NFmG1qvRW{{bYal@ar?lzY<|KrCOBsEE@qu*fUYwQ#I
zFrN+g^Q5YXo@D`sNgmu8qPi2B1A%c7Y*LQI!Cct$2xcjDWkq>Vi^0C`+%vo9*qfMD
zV4;gZ5L#;ecaH{Xgj|pHJYxBGoP0a`VB$c3tG0(7)?IvW^3s8;`uFjYl|2Rx&!X@5
z8wg+BeYYzb=HvgvBW&rmU}t-}l`So5lrpJjJza~b-@4tg7&r+CB^0Bvx_qMKrGu;N
zdN*rIq-G5|d)Rmekj76cSkb^6ucPO9kD7?gJ|2Rpq6Adh_o%{U9<^Q*BRGT>XpQ;F
zR`|~zSu;NqVd#lc2YjnNgs(s$`{);9!KG(yZ6{>i?aw~v3FMlDEG@&2H1&80#Z6KI
zG@W(&-L47;S%VUSjkoJ+wv}Svn+X;t&m-}pkJsctmPF3#>jtg%kfTXm*;_`rt4HMm
z9$_2j!g|@eM?L(}wP{W(0Mfm=HR!J`4UNzmAq{-tMoi68z9U(9`CYbF@zH`&*a&;V
z;{YCNZ{Hl>dV3c+v4d>*kiWjoP&oLaK+TfQq)1kM?o1Hs>uGK)-O)45#2eQ8sg*7w
zFaicS79B7MlT!4$H?p?_LwbUO&?&NLkQW#FUnXGdGvxU)7pu1eRwuMo@li~wV<7q8
zxyJF!R$Qubcs?uW1u~ecN3D$Y^_<{;Egt_bVy8JTv`9rKMZCp=*3e~)stqjg1G6&+
z9GzqH*BOhQ3S`I)>~aQWsY*}qJ#}3DTJ7Da1SMo)Qa40uTIj}A9dAxDk50L@)6qte
zb4OHD>GZzL7ru^f`E1D1vH-S{&M37>G#SC5bCdhS?QU|?B5D{Rn)pz?fe^oyUyy+8
zg`1({4uQ2sA&X`!3KRaf$J6w2syW#Pjxc~#RDZXBxkY}0N!olt{M3-+$SkQc%1<(>
zVzJH+za&QSEG8GyxC8I~G7vAaLb|K8oZpUby|>KKgMuL{pct1HxQmP8fe0WF)mC(~
z5V?Zg>h}~yY^8t$xCALJ%Xx=seyAKKEIK!`9Kc{zPc2&=^rR7Cf_#L;IrIIlJm?F0GD3<5tv1pQK8`rjMtypE^{sW
z6@rprg2O&}hy`4@gGsn=I4tQ|vr&$#y_0ez4)dvL731MiG(m3(dRFY7ZlC{es
zvs_xmCe$?WVhNr<4aKR`M$nHBZ>FF|v{&rzB>nU1tph=AoueX`ByQwFnKyTNUg*MS
z@QZ75Uq!JfLCvN+*&4kO+tRm1j9s>J?@973=hU~R+1eqHkkX+UqFO<>^XGv>Sle(tj(}hv*`-7K7x9
z^tL(ZomOq~-*+W?lT{%YH}sLG!q2)*l$6odEVx
zXK{CjRbRMoBz4gk1nufSEu{(<=_y+_9j)ETWYqg@jU&lmCskN-$E)0H=m47{GuTxK
zf^e|i6G|CwrH;$H|k3;QP2voY-O-Vj8re(1TZPnJ~30LuGdij{1v
zzRMYQ$kV#OwiW=ZTNf2*SdQL*aQRkN3YvJ?PD$fY(bvy3=TUsVa*l!@*kvI>Vd#|1
zAe#}7wHYY4W@9}(%Omb*d9&8Ukx&1S-;pf1#F6v
z0l58gmU8yJHIB*#^U0aH#d!asHen8uVHKhGGf_C!NMfyGcg2Z}J+-7Y_t3b>HVLld
zXX=>r42X8{25?aHl+*YXJhUeK8R>o1VH*i9Z~XJvtB3t?mm{V+EB5k>3(l>VGtAkq
z6lL2h(RGJPiw>_A1}`xW*$jb$K|BGsManYDOIL8$(uwr-$Q3ex=3Evt*j7((1HFkZ
z*T8!w6B1+%3dieGL(lLtAG^668JvY!rxD}^@XnZLKK)c=(Uxf&5ELj^i)ZBHr#SXv
zpENm7+p%{_$T@oT8k7_b>cCC}apLWmT65K!p!#3qPyQR=`JZzy3nkXx>fzVcZG9nb
zTr(?hCWkac4uu
zvu|--UC;`cZgMKjkE0A3TY{&_u`iWOW7`kb*1oEBu;bOY%~pECmf#*oBNObPWjJd<
znZtJQPdr{fXvE!U^T73TAPQi5j;$(C{I&;Hb9fW4z0e)uaUkQTdw*E3@*DWwo4b}7
z3wL=!xs9N+lnLX{;8}Su5USY66^Og1Kw*0=-c}zlvcICUZISoARhRx|3-~Po)3p_(
zOS#>rcAr|Sp`8-nv?MtP(jD4XxIjaIUhlq!X^M4kZUc8%x6cHnshf4j{w$;Z{uFcP
zgSW+K1QCYMl#w=;a8#eFrrwcaf5@r#5vtdeSIe^YaCz{}@2ylNFtaQ>+MiX-mYwYQb7Te$n6MeQ{=-%|OZ(?hnyl#luYBY{me>>6A&O*E?Up+E9W^D2^*m?9K`xe
zQ7MK+p%KmO%5%wfD0QM0UABilJWzq>yq@yDd~W^FyXz!Sc;O5)LrYE$>hTa1y#2@P
zruV&3l2t{OZ9I=IY=Z?)nf;sOjDJTOu*`W23biEAByhLGZK>nZ@Pb&cD_rLpS%qlM
z&qI%=HGyCDaCz0d3XRJS0lO=no4e|p)ft9AwgjWpdJB@|ltYX+!W*`LG~UvI$dzb5
zMQYDp;BP*c4!$}b15e0SpZc~*HMw$m+%Dg
zD#PN@b_!AHA>sBc?RPNRLwR;Znw4eNllozUidramILS#egCO~)gJgaSeH|J*>rHTp
zEv7AJ%}3hB-j`UdxDMNy4ajfs>K#Ffnlet~c9)+y%>^VLW-@#>Yk7V`wf<9i_P(F#
z2KlQlX(E55oQ1W^Y7{DQiY^5d?eqtM&pL3OkEBNO1Y4TC4Tt6M>0f_Zu%-!uja%Ku
z%;a!Rro>eawj(TOCqj0~UuI}Vb^_H$&0%b~w!qO|TOOW0nKA}xWP*+$p^J`r*@p_D
z`Rpc-gKR;efLnTDS%)H+$*bM6V?BpUj=2^9a5j6%5xU=flO}8M-k{%2GZ04wevZkvDdxr&W&qk{KmwK<>D
z7DupLz4DIa$-Rc+sgSw4t&c$1jkvHuw)#99BP|nq_P=n||G#we0w38Yj_-07FU|_W
zYp@wE%rKqRtl@q_!9e3tH8{oo60&-8^sSCoR5*-B!(t6l*-+9oNiX8^Zg8jQ1_RqB
z+=JbER%Oep^~(IxhAjENyh=d$B<3${P(7{gol0+HMBxk$vv9RRF6K~8Ae@TcGQ$=m=ZQA3$L~cj0Zf&l$IB3h#*6rHbBCh-id@O`o4m6=nL+G>-xsZtY)5)_
z9%i@u#%DJ{m5wG=PHKC+mLEIhNrpa}^Ut758g90(yP?mMtdsw=T$6h)lrx&C3el-o
ziG$9^6`BDIMu)`9^bOV=+9B@6oZ~mU_LZUs*wY2>V@~$(%@LL>NF-r%zn;ycHQowg
zF!0rV$9-;6>529q?6p{0ZXOW=6WVb5Z@~p$GpF`zv_m1oYD84!KFBf6b!}I~g
z3y$fvMHT$={hg(q4u1Pq^m`I(nDomI#aF~n1)T-)nBEEb+o`gCNyk&E9r$gE{0n%O
zWfJ}!{aZ3F%gEVCtXi^jM~NTc`w*QbR{A`+yoq5KKCCA^^XCb>)?eslB%9S33l40Y
z*`g1$7nXXDEIh{#+>~4`qOLjyS-!RXoB|5U6xmlaAGdwba4|7v%sH5ul{H~W+WABT
z{U|xTR4Vg+)N0k-Gq`QXqw;wUo7XZO)NY-&%uq;c`KFuc;n+3maj45eAMHR!6Q-wk
z65vO#-eQ~|eW+B6ZjKx!hy@I^Iktnj%kK$P+;Hd*i_bgUUyv^LB?SLq>#GmxNu4!-
zA55*b;2W4OW0Jr*P=j0-R?ENEb&(7EosZ?DgS_Aut(cDKn%q{|WH~2WCeaESzIKAc
z4F*W=Pnvq{c~gr+E&+=p{x$GGRg$Vy<{=2g%e$d`9huqRC?g-_ttEHv-;hOtSgxIh;-<=xd!NdSU_Bl_Imqnqp(FqW~1&VH9pf=TpbKXp&qSct@8wz*q+RIA%JBY*!f*|@jEZ};a
z0HzttMK0PR$*7+D?~3Ao!dA9(nj`%dgHPao{WZ1cLyKl?(_!smJ!~z<>x*J@@!Tml
zM3zW6&Ooe}?M{kAaJVI0ev?rO`kSI=diI0*nj}%Qyp|(DbVg!X0CaA9d<7P=7W-;v
zXW4qW&RW3@TjNHHjvsL&{SmU?0e6Q5EE61DgX#_ovsoI-e6hK84+M_IfNYoQerH!Q
zFHR~u;z==INleFV&Xc8YlJQQ&k;uh5Qua|Q+~=stFRVIfHyys~w=$+HuM-gH|Kcsn
zr8EO$xS=fvN*as9^3uX9l_>|MigEDteP7`6#a;Q}s(V8VvIcEwn{s-iS1Z4nhC?yj
z-p*#>!_SmbD|>;+3w5jJevJi!TYAjDq&4uAl{-2=S5W@`l*bwTD2Mjqu_h&Do41OF
zq1N?o7=Mcjw}^~3x=2tpuGuDPlZ^
zGmatrw9%0QpX4lsh>!8q1H8;!{j@t@acSK9TJVlgH>&61nMrO~tvc(bfcI+fbo}&8
z=IA#e-Tqi1zT=`s%4|!o6sM0FPSKs;j}84x?-n=MQMh_EB5t6dK%PjS-yhT&%^ULI
zmgGabAS?z!1@B9RlJF3;1rOhB#DdRIA&>2MAIA
z7}+#XX=?Xu-*eO2^_LzxF$IHsfG#hX5DJvPEfcedu+lP+G0jDfhe^iisc$HK3=|u2
ziyMV_5c@>bypFzy?YH%L)UQVgcQlIDX59|A`?Bc0v3nz4X(Eq1$X8P!
zLvj#b3bUqSQH57`fXGotdWWQr_BsSu25DMH923C2-b0e@uDG5&MCK!TQZwxI(oaRa
zzdr%R%3RR2mfk7MbW&on4+xIa3m2D(s^9)&@G|CUWzpbBZyR_WRb=|t=s42O5qas-
z;OvXiWsSD%p~KD2;e(<8lfa;mL&Ga6?WknGfnp?fb%NeVW?oD)bL}YK+Ah;wJ-kI&1jBze{U_?(9m#9
zirp`@-$$>W;-}%UQaL?a<3gS@#J9WVIRtCk_AE8C1qEuMyJ5WQO0nfll3WIx*3LJP
zqOZoDVk>&z;0HxXReSlRl-9C!-QjRp6vVu^AQ8i?=-_w<<_$!p%;dTkr1&mm?dH&o
zuLJI4hF^;5T|oGYOYJ+}J=(o`w>WmjN_;vv
zX9|tD4&t0q74}ZKHA<9x(iX@r>K+KEIo{M+mAsp#1~jk
zG7keH8|+laX8e|Ps}$<5@jeW<$YHv8c=X)aYM|B(LZZFE$cfVWJtWii)6f)
zFC?%&oGx}%`j!mxcYa38B94kO(&pKJnU$i=?v(%a?QLLjI}mUE6`-a`2%r*-B`z#C
zI%>f179tLWAmYvB0Uh=$_e;vtF6z!9?JnoCV7=4y9#Au>tPuvpJNGHMgs
z7KY1(m)-qG@X+|l6|XCILK|@5J@kJcR}(MfmVnD~hNhv?gusV1l{Zpd7eNpyf_wwukLC3&c5w
z)(s5}eQ*QhAq7~t`Vxu35hE-!LbR^5Cl2Fb(n9k!m#jAbOn3)EPtGp>nmXiET2pFY
z$7%VstUjirUzBXqZ&Bt%`)CQ}aW8IgJzw2@NzHrNSQqeHHNCoIWc-CX7#ylV#nJ1(jBVSJF#)5_^$lC&r%Qf1m)5m
zO=cF{Eez+7>Y6ugFIowgZxjOy+CUa&p7I+QRK>W8XjU^9p`Ht|mgaD_`4OGIFy4vw|8omHY5V
z%vCWIe{>3|#ud;Y3<%WDW{u5d;P7Z#u$M*tfZKyi9_8uG=k@oyTCL5pmuDpD9SkRR
z?{z}Hv-{p%64<2m6=FNOv?+?GO%C53YB++eiQ
zBij$u%h9#^!v+P-UgT`4ei5@&(;Qg?TgwE6a;ZdrZqSW!$hBE7fIOn1U)dmmVvsH#
zAD8~BS=&ZpwhuRI$%@5iR0TEqnI6w86!OBh+QJ4AsdVYm_ScHz*J
zZK0(nFSZpH+zPOS?or+HmNBccUe3urUa
zbCA4iS&=TcC3LN;QPbpbIQ4X26JBq#-aK;1!
z-4k~s__}cDR8JlL=+N{rG?m$kE{9amIvqV9Omrvj$5wUvCe+ql7hXr*c}4R%Xux+s
zx3w}zh=+0MO1l&pp2STiQKR=B=4nr!1zl)))BHM5gIfs=xxT38EJBJd<3fr^BrNGh
z6m^&yS$9W5ZI9FrOcyNt8fG_A;g{H-)w|8BBC|4X{`ZOc|0`DC5m&Cg&lU_VQ}f44
zpuR#33&m@5_TgW(4Y3iySeZK=*4!iWD1i0whkN1Dh6H$;8anui#O2JtZsBu<@7VH;
zi}+rb8nJ2tCbgPK3_kQM?`*#sJFR5W({L365;ic^-ws{D$UsgdQY3W;&}n~xlX9~V
z6?s5q$rQ>FBmE#dY*|JEG;f1t
zJ)h4}f%2{EC0`Th3vRy1*~)a?j3q>QV=<#qurefla)uEIbe@pC$9o$&Pz1w>mae~-
zrS~@UzO`?rB3@R%A=!Dxy0yIPtQdwmnjt+wB>+@gypO?x
zuyCJp-^l*AD84@(X1r>*1OnO0iyrJ`kJtu`e57--vrKYqZN*HVpa6IQ
zjUUQ12)SXDVjO)Z4TnSeA@kOBlLH-GdqfL
zyC60(L9r3ntT5Q|!iGXAvgibGh+Zg3hGL4I^{PFM{S%6vlAK87sM0_~c-^@a9`pW@
zmFWPVGnHEAWm<_|Q_em@0c=%G&evzrD*|O$OQoqsC*g%lPrmo%Wd-5q><-t;);g6I
zhx;8xc!Gz`!X*hBl44BL#k_>O@0dr<p2_7evf8SYB@DFj`hj4M(U_aM*#~kp{K^2$X(Lu1k_ehip$TID(B!5~}
zGRs2S!b*(O%ufpiEJ6MQ!mK}YhEkG$M=$pB#y^>!Ut22zUu`K6iT15^ivz7w772Pu
zu#hW$1m%rmL&>f-6OXXW$_&JOa`m;XXOV?2m43>
zH^`(nJD_4hA*vC_F8x=2d)s_#X0u9ELL_EjhW?gMiSm4yh!;_2j}3_uWf@}i&tB5@
zegB>eI3hu9;FGAVN7{aDvscTFU&5`qccLI&`V&VrI=Fc&!irmq?sEt$sZ8N#ZkFTL
zZ=?I&l9#?mOn-s8-!h+Yg`8)zU;{NCgP7mL{r=fvzKGZG*-d6*zpUW97nWE%Nr2=-
zJWXP3t$5i(4h}ol;*5?I4aD?I-{~~Ww<~L{Mn8Fd?|jTue_ej`M)>Tr8E0q@?ji=6
zvUre!>3X)bI8U!W`oazuIDE+rJEHU~da;D^FPSF3L+wt!_n$QpC3jC~RacUy&B3$j
znC?V>K){cFm7aottd*jEM%rxPa`77^{Eiz9^<54Z1ZJaAW*lbF%&xWeD`@|SXPYFF
z(Ea>~-DHRD>>H+Shf|S*>scli@rsa+CR~i*;65=H!X#8YI3XZ^uKn}-Yw;Nk?GGW^
zK}d^;M^a0pjYSu}YDnUDB9m43^&ZrgxajBAm(1(7zyxzl