A fork of Simple Time Tracker with WearOS support. (Now integrated upstream)
0

Configure Feed

Select the types of activity you want to include in your feed.

add untracked time hint

razeeman (Nov 26, 2023, 12:19 PM +0300) fb9331cd c9cad814

+288 -52
+1
core/src/main/res/values-ar/strings.xml
··· 114 114 <string name="change_record_adjust">تغيير</string> 115 115 <string name="change_record_change_prev_record">تغيير وقت التتبع السابق أيضا</string> 116 116 <string name="change_record_change_adjacent_records">تغيير وقت التتبع المحاذي أيضا</string> 117 + <string name="change_record_untracked_time_hint">الوقت غير المُتعقب هو الوقت الذي لم يتم فيه تعقب أي نشاط. يمكن تعطيله في الإعدادات</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">تم أرشفة النشاط</string>
+1
core/src/main/res/values-ca/strings.xml
··· 114 114 <string name="change_record_adjust">Canvi</string> 115 115 <string name="change_record_change_prev_record">També canvia el temps de l\'enregistrament anterior</string> 116 116 <string name="change_record_change_adjacent_records">També canvia el temps dels enregistraments adjacents</string> 117 + <string name="change_record_untracked_time_hint">El temps sense seguiment és el temps en què no s\'ha fet el seguiment de cap activitat. Es pot desactivar a la configuració</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Activitat arxivada</string>
+1
core/src/main/res/values-de/strings.xml
··· 114 114 <string name="change_record_adjust">Ändern</string> 115 115 <string name="change_record_change_prev_record">Ändern Sie auch die Zeit des vorherigen Datensatzes</string> 116 116 <string name="change_record_change_adjacent_records">Ändern Sie auch die Zeit benachbarter Datensätze</string> 117 + <string name="change_record_untracked_time_hint">Die nicht erfasste Zeit ist die Zeit, in der keine Aktivität erfasst wurde. Es kann in den Einstellungen deaktiviert werden</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Aktivität archiviert</string>
+1
core/src/main/res/values-es/strings.xml
··· 114 114 <string name="change_record_adjust">Cambio</string> 115 115 <string name="change_record_change_prev_record">También cambia el tiempo del registro anterior</string> 116 116 <string name="change_record_change_adjacent_records">También cambia la hora de los registros adyacentes</string> 117 + <string name="change_record_untracked_time_hint">El tiempo sin seguimiento es el momento en el que no se realizó un seguimiento de ninguna actividad. Se puede desactivar en la configuración.</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Actividad archivada</string>
+1
core/src/main/res/values-fa/strings.xml
··· 114 114 <string name="change_record_adjust">تغییر</string> 115 115 <string name="change_record_change_prev_record">همچنین زمان تاریخچه قبلی را تغییر دهید</string> 116 116 <string name="change_record_change_adjacent_records">همچنین زمان تاریخچه های مجاور را تغییر دهید</string> 117 + <string name="change_record_untracked_time_hint">زمان ردیابی نشده زمانی است که هیچ فعالیتی ردیابی نشده است. در تنظیمات می توان آن را غیرفعال کرد</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">فعالیت بایگانی شد</string>
+1
core/src/main/res/values-fr/strings.xml
··· 114 114 <string name="change_record_adjust">Changement</string> 115 115 <string name="change_record_change_prev_record">Modifier également l\'heure de l\'enregistrement précédent</string> 116 116 <string name="change_record_change_adjacent_records">Modifier également l\'heure des enregistrements adjacents</string> 117 + <string name="change_record_untracked_time_hint">Le temps non suivi est le temps pendant lequel aucune activité n\'a été suivie. Il peut être désactivé dans les paramètres</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Activité archivée</string>
+1
core/src/main/res/values-hi/strings.xml
··· 114 114 <string name="change_record_adjust">बदलना</string> 115 115 <string name="change_record_change_prev_record">पिछले रिकॉर्ड का समय भी बदलें</string> 116 116 <string name="change_record_change_adjacent_records">पास के रिकॉर्ड का समय भी बदलें</string> 117 + <string name="change_record_untracked_time_hint">अनट्रैक्ड टाइम वह समय है जब किसी भी गतिविधि को ट्रैक नहीं किया गया था। इसे सेटिंग्स में अक्षम किया जा सकता है</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">संग्रहीत गतिविधि</string>
+1
core/src/main/res/values-in/strings.xml
··· 114 114 <string name="change_record_adjust">Mengubah</string> 115 115 <string name="change_record_change_prev_record">Juga ubah waktu rekaman sebelumnya</string> 116 116 <string name="change_record_change_adjacent_records">Juga ubah waktu catatan yang berdekatan</string> 117 + <string name="change_record_untracked_time_hint">Waktu yang tidak terlacak adalah waktu ketika tidak ada aktivitas yang terlacak. Itu dapat dinonaktifkan di pengaturan</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Kegiatan dihapuskan</string>
+1
core/src/main/res/values-it/strings.xml
··· 114 114 <string name="change_record_adjust">Modificare</string> 115 115 <string name="change_record_change_prev_record">Cambia anche l\'ora della registrazione precedente</string> 116 116 <string name="change_record_change_adjacent_records">Cambia anche l\'ora dei record adiacenti</string> 117 + <string name="change_record_untracked_time_hint">Il tempo non tracciato è il tempo in cui non è stata tracciata alcuna attività. Può essere disabilitato nelle impostazioni</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Attività archiviata</string>
+1
core/src/main/res/values-ja/strings.xml
··· 114 114 <string name="change_record_adjust">変更する</string> 115 115 <string name="change_record_change_prev_record">前のレコードの時刻も変更</string> 116 116 <string name="change_record_change_adjacent_records">隣接レコードの時刻も変更</string> 117 + <string name="change_record_untracked_time_hint">未追跡時間とは、アクティビティが追跡されなかった時間です。設定で無効にすることができます</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">アクティビティをアーカイブ</string>
+1
core/src/main/res/values-ko/strings.xml
··· 114 114 <string name="change_record_adjust">변경</string> 115 115 <string name="change_record_change_prev_record">이전 기록도 함께 변경</string> 116 116 <string name="change_record_change_adjacent_records">관련 기록의 시간도 함께 변경</string> 117 + <string name="change_record_untracked_time_hint">추적되지 않은 시간은 활동이 추적되지 않은 시간입니다. 설정에서 비활성화할 수 있습니다</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">활동 보관됨</string>
+1
core/src/main/res/values-nl/strings.xml
··· 114 114 <string name="change_record_adjust">Verandering</string> 115 115 <string name="change_record_change_prev_record">Wijzig ook de tijd van het vorige record</string> 116 116 <string name="change_record_change_adjacent_records">Wijzig ook de tijd van aangrenzende records</string> 117 + <string name="change_record_untracked_time_hint">Niet-bijgehouden tijd is de tijd waarin geen activiteit is bijgehouden. Het kan worden uitgeschakeld in de instellingen</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Activiteit gearchiveerd</string>
+1
core/src/main/res/values-pt/strings.xml
··· 114 114 <string name="change_record_adjust">Mudar</string> 115 115 <string name="change_record_change_prev_record">Mude também a hora do registro anterior</string> 116 116 <string name="change_record_change_adjacent_records">Também altere a hora dos registros adjacentes</string> 117 + <string name="change_record_untracked_time_hint">O tempo não rastreado é o tempo em que nenhuma atividade foi rastreada. Pode ser desativado nas configurações</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Atividade arquivada</string>
+1
core/src/main/res/values-ru/strings.xml
··· 114 114 <string name="change_record_adjust">Изменить</string> 115 115 <string name="change_record_change_prev_record">Также изменить время предыдущей записи</string> 116 116 <string name="change_record_change_adjacent_records">Также изменить время соседних записей</string> 117 + <string name="change_record_untracked_time_hint">Неотслеживаемое время - это время, когда никакая активность не отслеживалась. Его можно отключить в настройках</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Активность перемещена в архив</string>
+1
core/src/main/res/values-sv/strings.xml
··· 114 114 <string name="change_record_adjust">Förändra</string> 115 115 <string name="change_record_change_prev_record">Ändra även tid för tidigare händelse</string> 116 116 <string name="change_record_change_adjacent_records">Ändra också tiden för de intilliggande händelserna</string> 117 + <string name="change_record_untracked_time_hint">Ospårad tid är tid då ingen aktivitet spårades. Det kan inaktiveras i inställningarna</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Aktivitet arkiverad</string>
+1
core/src/main/res/values-tr/strings.xml
··· 114 114 <string name="change_record_adjust">Değiştirmek</string> 115 115 <string name="change_record_change_prev_record">Ayrıca önceki kaydın zamanını değiştir</string> 116 116 <string name="change_record_change_adjacent_records">Bitişik kayıtların zamanını da değiştir</string> 117 + <string name="change_record_untracked_time_hint">Takip edilmeyen zaman, hiçbir aktivitenin takip edilmediği zamandır. Ayarlardan devre dışı bırakılabilir</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Aktivite arşivlendi</string>
+1
core/src/main/res/values-uk/strings.xml
··· 114 114 <string name="change_record_adjust">Зміна</string> 115 115 <string name="change_record_change_prev_record">Також змінити час попереднього запису</string> 116 116 <string name="change_record_change_adjacent_records">Також змінити час суміжних записів</string> 117 + <string name="change_record_untracked_time_hint">Невідстежуваний час – це час, коли жодна діяльність не відстежувалася. Його можна вимкнути в налаштуваннях</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Активність переміщено до архіву</string>
+1
core/src/main/res/values-zh-rTW/strings.xml
··· 114 114 <string name="change_record_adjust">改變</string> 115 115 <string name="change_record_change_prev_record">也會改變前筆紀錄的時間</string> 116 116 <string name="change_record_change_adjacent_records">也會改變鄰近紀錄的時間</string> 117 + <string name="change_record_untracked_time_hint">未追蹤時間是指沒有追蹤任何活動的時間。可以在設定中停用它</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">已備存活動</string>
+1
core/src/main/res/values-zh/strings.xml
··· 114 114 <string name="change_record_adjust">改变</string> 115 115 <string name="change_record_change_prev_record">同时更改上一个记录的时间</string> 116 116 <string name="change_record_change_adjacent_records">同时更改相邻记录的时间</string> 117 + <string name="change_record_untracked_time_hint">未跟踪时间是指没有跟踪任何活动的时间。可以在设置中禁用它</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">活动已存档</string>
+1
core/src/main/res/values/strings.xml
··· 114 114 <string name="change_record_adjust">Change</string> 115 115 <string name="change_record_change_prev_record">Also change time of previous record</string> 116 116 <string name="change_record_change_adjacent_records">Also change time of adjacent records</string> 117 + <string name="change_record_untracked_time_hint">Untracked time is time when no activity was tracked. It can be disabled in settings</string> 117 118 118 119 <!-- Change record type --> 119 120 <string name="change_record_type_archived">Activity archived</string>
-9
features/feature_base_adapter/src/main/res/drawable/ic_remove.xml
··· 1 - <vector xmlns:android="http://schemas.android.com/apk/res/android" 2 - android:width="24dp" 3 - android:height="24dp" 4 - android:viewportWidth="24" 5 - android:viewportHeight="24"> 6 - <path 7 - android:fillColor="#FF000000" 8 - android:pathData="M14.59,8L12,10.59 9.41,8 8,9.41 10.59,12 8,14.59 9.41,16 12,13.41 14.59,16 16,14.59 13.41,12 16,9.41 14.59,8zM12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/> 9 - </vector>
+3 -33
features/feature_base_adapter/src/main/res/layout/item_hint_big_layout.xml
··· 1 1 <?xml version="1.0" encoding="utf-8"?> 2 - <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 - xmlns:app="http://schemas.android.com/apk/res-auto" 4 - xmlns:tools="http://schemas.android.com/tools" 2 + <com.example.util.simpletimetracker.feature_views.HintBigView xmlns:android="http://schemas.android.com/apk/res/android" 3 + android:id="@+id/itemHintBig" 5 4 android:layout_width="match_parent" 6 5 android:layout_height="wrap_content" 7 6 android:layout_marginHorizontal="16dp" 8 - android:layout_marginVertical="16dp" 9 - android:background="@drawable/bg_rounded_corners" 10 - android:backgroundTint="?appActiveColor" 11 - android:paddingHorizontal="16dp" 12 - android:paddingTop="16dp" 13 - android:paddingBottom="16dp"> 14 - 15 - <androidx.appcompat.widget.AppCompatImageView 16 - android:id="@+id/ivHintItemIcon" 17 - android:layout_width="wrap_content" 18 - android:layout_height="wrap_content" 19 - android:src="@drawable/info" 20 - android:tint="?appInfoColor" 21 - app:layout_constraintEnd_toEndOf="parent" 22 - app:layout_constraintStart_toStartOf="parent" 23 - app:layout_constraintTop_toTopOf="parent" /> 24 - 25 - <androidx.appcompat.widget.AppCompatTextView 26 - android:id="@+id/tvHintItemText" 27 - android:layout_width="0dp" 28 - android:layout_height="wrap_content" 29 - android:gravity="center" 30 - android:textColor="?appLightTextColor" 31 - app:layout_constraintBottom_toBottomOf="parent" 32 - app:layout_constraintEnd_toEndOf="parent" 33 - app:layout_constraintStart_toStartOf="parent" 34 - app:layout_constraintTop_toBottomOf="@id/ivHintItemIcon" 35 - tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc hendrerit, orci id consectetur consectetur, neque enim gravida quam, quis pellentesque enim velit quis lorem. Morbi sit amet efficitur turpis." /> 36 - 37 - </androidx.constraintlayout.widget.ConstraintLayout> 7 + android:layout_marginVertical="16dp" />
+14 -2
features/feature_change_record/src/main/res/layout/change_record_core_layout.xml
··· 6 6 android:layout_height="match_parent" 7 7 android:animateLayoutChanges="true"> 8 8 9 + <com.example.util.simpletimetracker.feature_views.HintBigView 10 + android:id="@+id/containerChangeRecordUntrackedHint" 11 + android:layout_width="match_parent" 12 + android:layout_height="wrap_content" 13 + android:layout_marginHorizontal="20dp" 14 + android:layout_marginTop="4dp" 15 + android:visibility="gone" 16 + app:itemCloseIconVisible="true" 17 + app:itemHintText="@string/change_record_untracked_time_hint" 18 + app:layout_constraintTop_toTopOf="parent" 19 + tools:visibility="visible" /> 20 + 9 21 <androidx.constraintlayout.widget.ConstraintLayout 10 22 android:id="@+id/containerChangeRecordTimes" 11 23 android:layout_width="match_parent" 12 24 android:layout_height="wrap_content" 13 - app:layout_constraintTop_toTopOf="parent"> 25 + app:layout_constraintTop_toBottomOf="@id/containerChangeRecordUntrackedHint"> 14 26 15 27 <androidx.cardview.widget.CardView 16 28 android:id="@+id/fieldChangeRecordTimeStarted" ··· 424 436 android:id="@+id/rvChangeRecordSearchComments" 425 437 android:layout_width="match_parent" 426 438 android:layout_height="match_parent" 427 - android:scrollbars="vertical" 428 439 android:layout_marginHorizontal="18dp" 440 + android:scrollbars="vertical" 429 441 android:visibility="gone" 430 442 tools:itemCount="1" 431 443 tools:listitem="@layout/change_record_comment_field_item"
+9
features/feature_views/src/main/res/drawable/ic_remove.xml
··· 1 + <vector xmlns:android="http://schemas.android.com/apk/res/android" 2 + android:width="24dp" 3 + android:height="24dp" 4 + android:viewportWidth="24" 5 + android:viewportHeight="24"> 6 + <path 7 + android:fillColor="#FF000000" 8 + android:pathData="M14.59,8L12,10.59 9.41,8 8,9.41 10.59,12 8,14.59 9.41,16 12,13.41 14.59,16 16,14.59 13.41,12 16,9.41 14.59,8zM12,2C6.47,2 2,6.47 2,12s4.47,10 10,10 10,-4.47 10,-10S17.53,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/> 9 + </vector>
+52
features/feature_views/src/main/res/layout/hint_big_view_layout.xml
··· 1 + <?xml version="1.0" encoding="utf-8"?> 2 + <merge xmlns:android="http://schemas.android.com/apk/res/android" 3 + xmlns:app="http://schemas.android.com/apk/res-auto" 4 + xmlns:tools="http://schemas.android.com/tools" 5 + android:id="@+id/containerChangeRecordUntrackedHint" 6 + android:layout_width="match_parent" 7 + android:layout_height="wrap_content" 8 + tools:background="@drawable/bg_rounded_corners" 9 + tools:backgroundTint="?appActiveColor" 10 + tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout"> 11 + 12 + <androidx.appcompat.widget.AppCompatImageView 13 + android:id="@+id/ivHintBigIcon" 14 + android:layout_width="wrap_content" 15 + android:layout_height="wrap_content" 16 + android:layout_marginTop="16dp" 17 + android:src="@drawable/info" 18 + android:tint="?appInfoColor" 19 + android:visibility="gone" 20 + app:layout_constraintEnd_toEndOf="parent" 21 + app:layout_constraintStart_toStartOf="parent" 22 + app:layout_constraintTop_toTopOf="parent" 23 + tools:visibility="visible" /> 24 + 25 + <androidx.appcompat.widget.AppCompatTextView 26 + android:id="@+id/tvHintBigText" 27 + android:layout_width="0dp" 28 + android:layout_height="wrap_content" 29 + android:layout_marginHorizontal="24dp" 30 + android:layout_marginBottom="16dp" 31 + android:gravity="center" 32 + android:textColor="?appLightTextColor" 33 + app:layout_constraintBottom_toBottomOf="parent" 34 + app:layout_constraintEnd_toEndOf="parent" 35 + app:layout_constraintStart_toStartOf="parent" 36 + app:layout_constraintTop_toBottomOf="@id/ivHintBigIcon" 37 + app:layout_goneMarginTop="16dp" 38 + tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc hendrerit, orci id consectetur consectetur, neque enim gravida quam, quis pellentesque enim velit quis lorem. Morbi sit amet efficitur turpis." /> 39 + 40 + <androidx.appcompat.widget.AppCompatImageView 41 + android:id="@+id/btnHintBigClose" 42 + android:layout_width="24dp" 43 + android:layout_height="24dp" 44 + android:layout_margin="2dp" 45 + android:src="@drawable/ic_remove" 46 + android:tint="?appLightTextColor" 47 + android:visibility="gone" 48 + app:layout_constraintEnd_toEndOf="parent" 49 + app:layout_constraintTop_toTopOf="parent" 50 + tools:visibility="visible" /> 51 + 52 + </merge>
+6
features/feature_views/src/main/res/values/attrs.xml
··· 150 150 <attr name="drawIcons" format="boolean" /> 151 151 <attr name="drawParticles" format="boolean" /> 152 152 </declare-styleable> 153 + 154 + <declare-styleable name="HintBigView"> 155 + <attr name="itemHintText" format="reference" /> 156 + <attr name="itemInfoIconVisible" format="boolean" /> 157 + <attr name="itemCloseIconVisible" format="boolean" /> 158 + </declare-styleable> 153 159 </resources>
+6 -2
core/src/main/java/com/example/util/simpletimetracker/core/mapper/CategoryViewDataMapper.kt
··· 192 192 193 193 fun mapToCategoriesFirstHint(): ViewHolderType { 194 194 return HintBigViewData( 195 - text = resourceRepo.getString(R.string.categories_record_type_hint) 195 + text = resourceRepo.getString(R.string.categories_record_type_hint), 196 + infoIconVisible = true, 197 + closeIconVisible = false, 196 198 ) 197 199 } 198 200 199 201 fun mapToTagsFirstHint(): ViewHolderType { 200 202 return HintBigViewData( 201 - text = resourceRepo.getString(R.string.categories_record_hint) 203 + text = resourceRepo.getString(R.string.categories_record_hint), 204 + infoIconVisible = true, 205 + closeIconVisible = false, 202 206 ) 203 207 } 204 208
+10
core/src/main/java/com/example/util/simpletimetracker/core/mapper/RecordViewDataMapper.kt
··· 121 121 fun mapToNoRecords(): ViewHolderType { 122 122 return HintBigViewData( 123 123 text = resourceRepo.getString(R.string.no_records_exist), 124 + infoIconVisible = true, 125 + closeIconVisible = false, 126 + ) 127 + } 128 + 129 + fun mapToUntrackedTimeHint(): ViewHolderType { 130 + return HintBigViewData( 131 + text = resourceRepo.getString(R.string.change_record_untracked_time_hint), 132 + infoIconVisible = false, 133 + closeIconVisible = true, 124 134 ) 125 135 } 126 136 }
+5
data_local/src/main/java/com/example/util/simpletimetracker/data_local/repo/PrefsRepoImpl.kt
··· 241 241 KEY_REPEAT_BUTTON_TYPE, 0 242 242 ) 243 243 244 + override var untrackedTimeHintWasHidden: Boolean by prefs.delegate( 245 + KEY_UNTRACKED_TIME_HINT_WAS_HIDDEN, false 246 + ) 247 + 244 248 override fun setWidget(widgetId: Int, recordType: Long) { 245 249 prefs.edit().putLong(KEY_WIDGET + widgetId, recordType).apply() 246 250 } ··· 434 438 private const val KEY_AUTOMATIC_EXPORT_ERROR = "automaticExportError" 435 439 private const val KEY_AUTOMATIC_EXPORT_LAST_SAVE_TIME = "automaticExportLastSaveTime" 436 440 private const val KEY_REPEAT_BUTTON_TYPE = "repeatButtonType" 441 + private const val KEY_UNTRACKED_TIME_HINT_WAS_HIDDEN = "untrackedTimeHintWasHidden" 437 442 private const val KEY_WIDGET = "widget_" 438 443 private const val KEY_STATISTICS_WIDGET_FILTERED_TYPES = "statistics_widget_filtered_types_" 439 444 private const val KEY_STATISTICS_WIDGET_FILTERED_CATEGORIES = "statistics_widget_filtered_categories_"
+8
domain/src/main/java/com/example/util/simpletimetracker/domain/interactor/PrefsInteractor.kt
··· 559 559 } 560 560 } 561 561 562 + suspend fun getUntrackedTimeHintWasHidden(): Boolean = withContext(Dispatchers.IO) { 563 + prefsRepo.untrackedTimeHintWasHidden 564 + } 565 + 566 + suspend fun setUntrackedTimeHintWasHidden(wasHidden: Boolean) = withContext(Dispatchers.IO) { 567 + prefsRepo.untrackedTimeHintWasHidden = wasHidden 568 + } 569 + 562 570 suspend fun clear() = withContext(Dispatchers.IO) { 563 571 prefsRepo.clear() 564 572 }
+2
domain/src/main/java/com/example/util/simpletimetracker/domain/repo/PrefsRepo.kt
··· 111 111 112 112 var repeatButtonType: Int 113 113 114 + var untrackedTimeHintWasHidden: Boolean 115 + 114 116 fun setWidget(widgetId: Int, recordType: Long) 115 117 116 118 fun getWidget(widgetId: Int): Long
+78
features/feature_views/src/main/java/com/example/util/simpletimetracker/feature_views/HintBigView.kt
··· 1 + package com.example.util.simpletimetracker.feature_views 2 + 3 + import android.content.Context 4 + import android.content.res.ColorStateList 5 + import android.util.AttributeSet 6 + import android.view.LayoutInflater 7 + import androidx.constraintlayout.widget.ConstraintLayout 8 + import androidx.core.view.isVisible 9 + import com.example.util.simpletimetracker.feature_views.databinding.HintBigViewLayoutBinding 10 + import com.example.util.simpletimetracker.feature_views.extension.getThemedAttr 11 + import com.example.util.simpletimetracker.feature_views.extension.setOnClick 12 + 13 + class HintBigView @JvmOverloads constructor( 14 + context: Context, 15 + attrs: AttributeSet? = null, 16 + defStyleAttr: Int = 0, 17 + ) : ConstraintLayout( 18 + context, 19 + attrs, 20 + defStyleAttr, 21 + ) { 22 + 23 + private val binding: HintBigViewLayoutBinding = HintBigViewLayoutBinding 24 + .inflate(LayoutInflater.from(context), this) 25 + 26 + var itemText: String = "" 27 + set(value) { 28 + field = value 29 + binding.tvHintBigText.text = value 30 + } 31 + 32 + var itemInfoIconVisible: Boolean = false 33 + set(value) { 34 + field = value 35 + binding.ivHintBigIcon.isVisible = value 36 + } 37 + 38 + var itemCloseIconVisible: Boolean = false 39 + set(value) { 40 + field = value 41 + binding.btnHintBigClose.isVisible = value 42 + } 43 + 44 + init { 45 + initProps() 46 + initAttrs(context, attrs, defStyleAttr) 47 + } 48 + 49 + fun setOnCloseClick(action: () -> Unit) { 50 + binding.btnHintBigClose.setOnClick(action) 51 + } 52 + 53 + private fun initProps() { 54 + setBackgroundResource(R.drawable.bg_rounded_corners) 55 + val backgroundTint = context.getThemedAttr(R.attr.appActiveColor) 56 + backgroundTintList = ColorStateList.valueOf(backgroundTint) 57 + } 58 + 59 + private fun initAttrs( 60 + context: Context, 61 + attrs: AttributeSet?, 62 + defStyleAttr: Int, 63 + ) { 64 + context.obtainStyledAttributes(attrs, R.styleable.HintBigView, defStyleAttr, 0) 65 + .run { 66 + if (hasValue(R.styleable.HintBigView_itemHintText)) itemText = 67 + getString(R.styleable.HintBigView_itemHintText).orEmpty() 68 + 69 + if (hasValue(R.styleable.HintBigView_itemInfoIconVisible)) itemInfoIconVisible = 70 + getBoolean(R.styleable.HintBigView_itemInfoIconVisible, false) 71 + 72 + if (hasValue(R.styleable.HintBigView_itemCloseIconVisible)) itemCloseIconVisible = 73 + getBoolean(R.styleable.HintBigView_itemCloseIconVisible, false) 74 + 75 + recycle() 76 + } 77 + } 78 + }
+8 -3
features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/hintBig/HintBigAdapterDelegate.kt
··· 4 4 import com.example.util.simpletimetracker.feature_base_adapter.databinding.ItemHintBigLayoutBinding as Binding 5 5 import com.example.util.simpletimetracker.feature_base_adapter.hintBig.HintBigViewData as ViewData 6 6 7 - fun createHintBigAdapterDelegate() = createRecyclerBindingAdapterDelegate<ViewData, Binding>( 7 + fun createHintBigAdapterDelegate( 8 + onCloseClick: () -> Unit = {}, 9 + ) = createRecyclerBindingAdapterDelegate<ViewData, Binding>( 8 10 Binding::inflate, 9 11 ) { binding, item, _ -> 10 12 11 - with(binding) { 13 + with(binding.itemHintBig) { 12 14 item as ViewData 13 15 14 - tvHintItemText.text = item.text 16 + itemText = item.text 17 + itemInfoIconVisible = item.infoIconVisible 18 + itemCloseIconVisible = item.closeIconVisible 19 + setOnCloseClick(onCloseClick) 15 20 } 16 21 }
+2
features/feature_base_adapter/src/main/java/com/example/util/simpletimetracker/feature_base_adapter/hintBig/HintBigViewData.kt
··· 4 4 5 5 data class HintBigViewData( 6 6 val text: String, 7 + val infoIconVisible: Boolean, 8 + val closeIconVisible: Boolean, 7 9 ) : ViewHolderType { 8 10 9 11 override fun getUniqueId(): Long = text.hashCode().toLong()
+2
features/feature_change_record/src/main/java/com/example/util/simpletimetracker/feature_change_record/view/ChangeRecordCore.kt
··· 152 152 btnChangeRecordContinue.setOnClick(viewModel::onContinueClick) 153 153 btnChangeRecordDuplicate.setOnClick(viewModel::onDuplicateClick) 154 154 btnChangeRecordMerge.setOnClick(viewModel::onMergeClick) 155 + containerChangeRecordUntrackedHint.setOnCloseClick(viewModel::onUntrackedHintCloseClick) 155 156 } 156 157 157 158 fun <T : ViewBinding> initViewModel( ··· 192 193 mergePreview.observe { setMergePreview(it, binding) } 193 194 splitPreview.observe { setSplitPreview(it, binding) } 194 195 adjustPreview.observe { setAdjustPreview(it, binding) } 196 + untrackedTimeHintVisibility.observe(containerChangeRecordUntrackedHint::visible::set) 195 197 } 196 198 } 197 199
+26
features/feature_change_record/src/main/java/com/example/util/simpletimetracker/feature_change_record/viewModel/ChangeRecordBaseViewModel.kt
··· 98 98 initial 99 99 } 100 100 } 101 + val untrackedTimeHintVisibility: LiveData<Boolean> by lazy { 102 + return@lazy MutableLiveData<Boolean>().let { initial -> 103 + viewModelScope.launch { 104 + initial.value = loadUntrackedTimeHintVisibility() 105 + } 106 + initial 107 + } 108 + } 101 109 val timeAdjustmentState: LiveData<TimeAdjustmentState> = MutableLiveData(TimeAdjustmentState.TIME_STARTED) 102 110 val saveButtonEnabled: LiveData<Boolean> = MutableLiveData(true) 103 111 val keyboardVisibility: LiveData<Boolean> = MutableLiveData(false) ··· 123 131 protected abstract val splitPreviewTimeEnded: Long 124 132 protected abstract val showTimeEndedOnSplitPreview: Boolean 125 133 protected abstract val adjustNextRecordAvailable: Boolean 134 + protected abstract val untrackedHintAvailable: Boolean 126 135 127 136 private var prevRecord: Record? = null 128 137 private var nextRecord: Record? = null ··· 445 454 } 446 455 } 447 456 457 + fun onUntrackedHintCloseClick() { 458 + viewModelScope.launch { 459 + prefsInteractor.setUntrackedTimeHintWasHidden(wasHidden = true) 460 + updateUntrackedTimeHintVisibility() 461 + } 462 + } 463 + 448 464 private suspend fun updateMergeData() { 449 465 changeRecordMergeDelegate.updateMergePreviewViewData( 450 466 mergeAvailable = mergeAvailable, ··· 662 678 isLoading = isLoading, 663 679 search = searchComment, 664 680 ) 681 + } 682 + 683 + private suspend fun updateUntrackedTimeHintVisibility() { 684 + untrackedTimeHintVisibility.set(loadUntrackedTimeHintVisibility()) 685 + } 686 + 687 + private suspend fun loadUntrackedTimeHintVisibility(): Boolean { 688 + val wasHidden = prefsInteractor.getUntrackedTimeHintWasHidden() 689 + val isCalendarView = prefsInteractor.getShowRecordsCalendar() 690 + return untrackedHintAvailable && isCalendarView && !wasHidden 665 691 } 666 692 667 693 companion object {
+1
features/feature_change_record/src/main/java/com/example/util/simpletimetracker/feature_change_record/viewModel/ChangeRecordViewModel.kt
··· 75 75 override val splitPreviewTimeEnded: Long get() = newTimeEnded 76 76 override val showTimeEndedOnSplitPreview: Boolean get() = true 77 77 override val adjustNextRecordAvailable: Boolean get() = true 78 + override val untrackedHintAvailable: Boolean get() = extra is ChangeRecordParams.Untracked 78 79 79 80 val record: LiveData<ChangeRecordViewData> by lazy { 80 81 return@lazy MutableLiveData<ChangeRecordViewData>().let { initial ->
+1
features/feature_change_running_record/src/main/java/com/example/util/simpletimetracker/feature_change_running_record/viewModel/ChangeRunningRecordViewModel.kt
··· 78 78 override val splitPreviewTimeEnded: Long get() = System.currentTimeMillis() 79 79 override val showTimeEndedOnSplitPreview: Boolean get() = false 80 80 override val adjustNextRecordAvailable: Boolean get() = false 81 + override val untrackedHintAvailable: Boolean get() = false 81 82 82 83 val record: LiveData<ChangeRunningRecordViewData> by lazy { 83 84 return@lazy MutableLiveData<ChangeRunningRecordViewData>().let { initial ->
+9
features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/interactor/RecordsViewDataInteractor.kt
··· 165 165 // Try to find if any record exists. 166 166 else -> recordInteractor.isEmpty() && runningRecordInteractor.isEmpty() 167 167 } 168 + val showUntrackedTimeHint = !prefsInteractor.getUntrackedTimeHintWasHidden() && 169 + records.any { it.data.value is RecordViewData.Untracked } 168 170 169 171 return records 170 172 .sortedByDescending { it.timeStartedTimestamp } ··· 174 176 showFirstEnterHint -> listOf(recordViewDataMapper.mapToNoRecords()) 175 177 it.isEmpty() -> listOf(recordViewDataMapper.mapToEmpty()) 176 178 else -> it + recordsViewDataMapper.mapToHint() 179 + } 180 + } 181 + .let { 182 + if (showUntrackedTimeHint) { 183 + listOf(recordViewDataMapper.mapToUntrackedTimeHint()) + it 184 + } else { 185 + it 177 186 } 178 187 } 179 188 .let(RecordsState::RecordsData)
+1 -1
features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/view/RecordsFragment.kt
··· 56 56 createEmptyAdapterDelegate(), 57 57 createLoaderAdapterDelegate(), 58 58 createHintAdapterDelegate(), 59 - createHintBigAdapterDelegate(), 59 + createHintBigAdapterDelegate(viewModel::onUntrackedHintCloseClick), 60 60 ) 61 61 } 62 62
+8 -1
features/feature_records/src/main/java/com/example/util/simpletimetracker/feature_records/viewModel/RecordsViewModel.kt
··· 137 137 } 138 138 } 139 139 140 - private fun updateRecords() = viewModelScope.launch() { 140 + fun onUntrackedHintCloseClick() { 141 + viewModelScope.launch { 142 + prefsInteractor.setUntrackedTimeHintWasHidden(wasHidden = true) 143 + updateRecords() 144 + } 145 + } 146 + 147 + private fun updateRecords() = viewModelScope.launch { 141 148 isCalendarView.set(prefsInteractor.getShowRecordsCalendar()) 142 149 143 150 when (val state = loadRecordsViewData()) {
+2
features/feature_running_records/src/main/java/com/example/util/simpletimetracker/feature_running_records/mapper/RunningRecordsViewDataMapper.kt
··· 19 19 resourceRepo.getString(R.string.running_records_add_type), 20 20 resourceRepo.getString(R.string.running_records_add_default), 21 21 ), 22 + infoIconVisible = true, 23 + closeIconVisible = false, 22 24 ) 23 25 } 24 26
+5
features/feature_statistics/src/main/java/com/example/util/simpletimetracker/feature_statistics/interactor/StatisticsViewDataInteractor.kt
··· 5 5 import com.example.util.simpletimetracker.core.mapper.ColorMapper 6 6 import com.example.util.simpletimetracker.core.mapper.GoalViewDataMapper 7 7 import com.example.util.simpletimetracker.core.mapper.RangeViewDataMapper 8 + import com.example.util.simpletimetracker.core.mapper.RecordViewDataMapper 8 9 import com.example.util.simpletimetracker.domain.UNCATEGORIZED_ITEM_ID 9 10 import com.example.util.simpletimetracker.domain.UNTRACKED_ITEM_ID 10 11 import com.example.util.simpletimetracker.domain.interactor.PrefsInteractor ··· 38 39 private val goalViewDataMapper: GoalViewDataMapper, 39 40 private val recordInteractor: RecordInteractor, 40 41 private val runningRecordInteractor: RunningRecordInteractor, 42 + private val recordViewDataMapper: RecordViewDataMapper, 41 43 ) { 42 44 43 45 fun mapFilter( ··· 180 182 // Try to find if any record exists. 181 183 else -> recordInteractor.isEmpty() && runningRecordInteractor.isEmpty() 182 184 } 185 + val showUntrackedTimeHint = !prefsInteractor.getUntrackedTimeHintWasHidden() && 186 + list.any { it.id == UNTRACKED_ITEM_ID } 183 187 184 188 // Assemble data. 185 189 val result: MutableList<ViewHolderType> = mutableListOf() ··· 191 195 } else { 192 196 if (forSharing) getSharingTitle(rangeLength, shift).let(result::addAll) 193 197 chart.let(result::add) 198 + if (showUntrackedTimeHint) recordViewDataMapper.mapToUntrackedTimeHint().let(result::add) 194 199 list.let(result::addAll) 195 200 totalTracked.let(result::add) 196 201 // If has any activity or tag other than untracked
+2
features/feature_statistics/src/main/java/com/example/util/simpletimetracker/feature_statistics/mapper/StatisticsViewDataMapper.kt
··· 81 81 fun mapToNoStatistics(): ViewHolderType { 82 82 return HintBigViewData( 83 83 text = resourceRepo.getString(R.string.no_statistics_exist), 84 + infoIconVisible = true, 85 + closeIconVisible = false, 84 86 ) 85 87 } 86 88
+1 -1
features/feature_statistics/src/main/java/com/example/util/simpletimetracker/feature_statistics/view/StatisticsFragment.kt
··· 151 151 createStatisticsGoalAdapterDelegate(), 152 152 createStatisticsTitleAdapterDelegate(), 153 153 createHintAdapterDelegate(), 154 - createHintBigAdapterDelegate(), 154 + createHintBigAdapterDelegate(viewModel::onUntrackedHintCloseClick), 155 155 createLoaderAdapterDelegate(), 156 156 createDividerAdapterDelegate(), 157 157 )
+7
features/feature_statistics/src/main/java/com/example/util/simpletimetracker/feature_statistics/viewModel/StatisticsViewModel.kt
··· 151 151 } 152 152 } 153 153 154 + fun onUntrackedHintCloseClick() { 155 + viewModelScope.launch { 156 + prefsInteractor.setUntrackedTimeHintWasHidden(wasHidden = true) 157 + updateStatistics() 158 + } 159 + } 160 + 154 161 private fun updateAnimateChartParticles() { 155 162 val shouldAnimate = isVisible && isChartAttached && !isTabScrolling && !isChartFilterOpened 156 163 animateChartParticles.set(shouldAnimate)