diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 7626f2c..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,128 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity -and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the - overall community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or - advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email - address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -nishant.28@outlook.com. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series -of actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or -permanent ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within -the community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.0, available at -https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. - -Community Impact Guidelines were inspired by [Mozilla's code of conduct -enforcement ladder](https://github.com/mozilla/diversity). - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9e46fb8..77e1df8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -33,8 +33,8 @@ android { applicationId = "org.nsh07.pomodoro" minSdk = 26 targetSdk = 36 - versionCode = 10 - versionName = "1.4.2" + versionCode = 11 + versionName = "1.4.3" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/org/nsh07/pomodoro/data/StatDao.kt b/app/src/main/java/org/nsh07/pomodoro/data/StatDao.kt index f1767f5..a58aff0 100644 --- a/app/src/main/java/org/nsh07/pomodoro/data/StatDao.kt +++ b/app/src/main/java/org/nsh07/pomodoro/data/StatDao.kt @@ -42,11 +42,16 @@ interface StatDao { @Query( "SELECT " + - "AVG(NULLIF(focusTimeQ1,0)) AS focusTimeQ1, " + - "AVG(NULLIF(focusTimeQ2,0)) AS focusTimeQ2, " + - "AVG(NULLIF(focusTimeQ3,0)) AS focusTimeQ3, " + - "AVG(NULLIF(focusTimeQ4,0)) AS focusTimeQ4 " + - "FROM (SELECT focusTimeQ1, focusTimeQ2, focusTimeQ3, focusTimeQ4 FROM stat ORDER BY date DESC LIMIT :n)" + "AVG(focusTimeQ1) AS focusTimeQ1, " + + "AVG(focusTimeQ2) AS focusTimeQ2, " + + "AVG(focusTimeQ3) AS focusTimeQ3, " + + "AVG(focusTimeQ4) AS focusTimeQ4 " + + "FROM (" + + "SELECT * FROM (" + + "SELECT focusTimeQ1, focusTimeQ2, focusTimeQ3, focusTimeQ4 FROM stat ORDER BY date DESC LIMIT :n" + + ") " + + "WHERE focusTimeQ1 != 0 OR focusTimeQ2 != 0 OR focusTimeQ3 != 0 OR focusTimeQ4 != 0 " + + ")" ) fun getLastNDaysAvgFocusTimes(n: Int): Flow diff --git a/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt b/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt index 595efae..07de4c2 100644 --- a/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt +++ b/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt @@ -3,6 +3,7 @@ package org.nsh07.pomodoro.service import android.annotation.SuppressLint import android.app.Service import android.content.Intent +import android.media.AudioAttributes import android.media.MediaPlayer import android.os.Build import android.os.IBinder @@ -78,7 +79,7 @@ class TimerService : Service() { override fun onCreate() { super.onCreate() timerRepository.serviceRunning = true - alarm = MediaPlayer.create(this, timerRepository.alarmSoundUri) + alarm = initializeMediaPlayer() } override fun onDestroy() { @@ -387,9 +388,29 @@ class TimerService : Service() { ) } + private fun initializeMediaPlayer(): MediaPlayer? { + return try { + MediaPlayer().apply { + setAudioAttributes( + AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) + .setUsage(AudioAttributes.USAGE_ALARM) + .build() + ) + timerRepository.alarmSoundUri?.let { + setDataSource(applicationContext, it) + prepare() + } + } + } catch (e: Exception) { + e.printStackTrace() + null + } + } + fun updateAlarmTone() { alarm?.release() - alarm = MediaPlayer.create(this, timerRepository.alarmSoundUri) + alarm = initializeMediaPlayer() } suspend fun saveTimeToDb() { @@ -417,4 +438,4 @@ class TimerService : Service() { enum class Actions { TOGGLE, SKIP, RESET, STOP_ALARM, UPDATE_ALARM_TONE } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt index 276f3de..5f604c1 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt @@ -35,7 +35,7 @@ import org.nsh07.pomodoro.data.TimerRepository @OptIn(FlowPreview::class, ExperimentalMaterial3Api::class) class SettingsViewModel( private val preferenceRepository: AppPreferenceRepository, - private val timerRepository: TimerRepository + private val timerRepository: TimerRepository, ) : ViewModel() { private val _preferencesState = MutableStateFlow(PreferencesState()) val preferencesState = _preferencesState.asStateFlow() @@ -50,12 +50,14 @@ class SettingsViewModel( TextFieldState((timerRepository.longBreakTime / 60000).toString()) } - val sessionsSliderState = SliderState( - value = timerRepository.sessionLength.toFloat(), - steps = 4, - valueRange = 1f..6f, - onValueChangeFinished = ::updateSessionLength - ) + val sessionsSliderState by lazy { + SliderState( + value = timerRepository.sessionLength.toFloat(), + steps = 4, + valueRange = 1f..6f, + onValueChangeFinished = ::updateSessionLength + ) + } val currentAlarmSound = timerRepository.alarmSoundUri.toString() @@ -203,9 +205,9 @@ class SettingsViewModel( SettingsViewModel( preferenceRepository = appPreferenceRepository, - timerRepository = appTimerRepository + timerRepository = appTimerRepository, ) } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/TimeColumnChart.kt b/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/TimeColumnChart.kt index a085850..497e553 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/TimeColumnChart.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/statsScreen/TimeColumnChart.kt @@ -7,14 +7,11 @@ package org.nsh07.pomodoro.ui.statsScreen -import android.graphics.Path -import android.graphics.RectF import androidx.compose.animation.core.AnimationSpec import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.MaterialTheme.motionScheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.patrykandpatrick.vico.compose.cartesian.CartesianChartHost @@ -35,7 +32,9 @@ import com.patrykandpatrick.vico.core.cartesian.data.CartesianChartModelProducer import com.patrykandpatrick.vico.core.cartesian.data.CartesianValueFormatter import com.patrykandpatrick.vico.core.cartesian.layer.ColumnCartesianLayer import com.patrykandpatrick.vico.core.common.Fill +import com.patrykandpatrick.vico.core.common.shape.CorneredShape import org.nsh07.pomodoro.utils.millisecondsToHours +import org.nsh07.pomodoro.utils.millisecondsToMinutes @OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -45,14 +44,15 @@ internal fun TimeColumnChart( thickness: Dp = 40.dp, columnCollectionSpacing: Dp = 4.dp, xValueFormatter: CartesianValueFormatter = CartesianValueFormatter.Default, - yValueFormatter: CartesianValueFormatter = CartesianValueFormatter { measuringContext, value, _ -> - millisecondsToHours(value.toLong()) + yValueFormatter: CartesianValueFormatter = CartesianValueFormatter { _, value, _ -> + if (value >= 60 * 60 * 1000) { + millisecondsToHours(value.toLong()) + } else { + millisecondsToMinutes(value.toLong()) + } }, animationSpec: AnimationSpec? = motionScheme.slowEffectsSpec() ) { - val radius = with(LocalDensity.current) { - (thickness / 2).toPx() - } ProvideVicoTheme(rememberM3VicoTheme()) { CartesianChartHost( chart = @@ -63,29 +63,7 @@ internal fun TimeColumnChart( rememberLineComponent( fill = fill(color), thickness = thickness, - shape = { _, path, left, top, right, bottom -> - if (top + radius <= bottom - radius) { - path.arcTo( - RectF(left, top, right, top + 2 * radius), - 180f, - 180f - ) - path.lineTo(right, bottom - radius) - path.arcTo( - RectF(left, bottom - 2 * radius, right, bottom), - 0f, - 180f - ) - path.close() - } else { - path.addCircle( - left + radius, - bottom - radius, - radius, - Path.Direction.CW - ) - } - } + shape = CorneredShape.Pill ) } ), diff --git a/app/src/main/java/org/nsh07/pomodoro/utils/Utils.kt b/app/src/main/java/org/nsh07/pomodoro/utils/Utils.kt index 6406065..4bbaabf 100644 --- a/app/src/main/java/org/nsh07/pomodoro/utils/Utils.kt +++ b/app/src/main/java/org/nsh07/pomodoro/utils/Utils.kt @@ -30,6 +30,15 @@ fun millisecondsToHours(t: Long): String { ) } +fun millisecondsToMinutes(t: Long): String { + require(t >= 0L) + return String.format( + Locale.getDefault(), + "%dm", + TimeUnit.MILLISECONDS.toMinutes(t) + ) +} + fun millisecondsToHoursMinutes(t: Long): String { require(t >= 0L) return String.format( diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml new file mode 100644 index 0000000..55344e5 --- /dev/null +++ b/app/src/main/res/values-fa/strings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 55344e5..2f3ad16 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -1,3 +1,6 @@ - \ No newline at end of file + प्रारंभ करें + विराम करें + ध्यान + diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml new file mode 100644 index 0000000..55344e5 --- /dev/null +++ b/app/src/main/res/values-iw/strings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml new file mode 100644 index 0000000..b25d003 --- /dev/null +++ b/app/src/main/res/values-uk/strings.xml @@ -0,0 +1,59 @@ + + + Почати + Стоп + Концентрація + Коротка перерва + Довга перерва + Вийти + Пропустити + Колірна схема + Аналіз продуктивності + Чорна тема + Вібрація + Тема + Налаштування + Тривалість сесії + Статистика + Сьогодні + Більше інформації + Щотижневий аналіз продуктивності + Минулого місяця + Щомісячний аналіз продуктивності + Перезапустити + Перейти до наступного + Далі + Таймер + Прогрес таймера + Зупинити + %1$s хв залишилося + Призупинено + Завершено + Далі: %1$s (%2$s) + Почати наступне + Обрати колірну схему + ОК + Динамічна + Колір + За замовчуванням (система) + Сигнал + Світла + Темна + Обрати тему + Тривалість концентрації в різні години дня + Звук сигналу + Використовувати чисту чорну тему + Звуковий сигнал по завершенні таймера + Увімкнути вібрацію після завершення таймера + Інтервали концентрації уваги в одній сесії: %1$d + «Сесія» - це послідовність інтервалів Pomodoro, що містить інтервали концентрації, короткі перерви та довгу перерву. Остання перерва сесії є завжди довгою. + Перерва + Минулого тижня + концентрацій на день (середнє значення) + Зупинити сигнал? + Поточна сесія таймера завершена. Натисніть будь-де, щоб зупинити сигнал. + %1$d з %2$d + Більше + Пауза + Грати + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000..fcc8a7d --- /dev/null +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,59 @@ + + + 开始 + 停止 + 专注 + 短休息 + 长休息 + 退出 + 跳过 + 停止响铃 + 还剩 %1$s 分钟 + 已暂停 + 已完成 + 下一步: %1$s (%2$s) + 开始下一个 + 选择配色方案 + 好的 + 配色方案 + 动态 + 颜色 + 系统默认 + 响铃 + 亮色 + 暗色 + 选择主题 + 工作效率分析 + 每日不同时间的专注时长 + 铃声 + 黑色主题 + 使用纯黑主题 + 计时结束时响铃 + 振动 + 计时结束时振动 + 主题 + 设置 + 小节长度 + 一小节内的专注时段: %1$d + 一个“小节”是一系列包含专注时段、短休息时段和长休息时段的番茄钟时段。一个小节的最后一个休息时段始终是长休息时段。 + 统计 + 今日 + 休息 + 上周 + 每日专注时长 (平均) + 更多信息 + 周生产力分析 + 上月 + 月生产力分析 + 要停止响铃吗? + 当前计时小节已完成. 轻触任何位置来停止响铃. + 更多 + 暂停 + 开始 + 重新开始 + 跳过到下一个 + 接下来是 + 计时 + 计时器进度 + %1$d 的 %2$d + diff --git a/fastlane/metadata/android/en-US/changelogs/11.txt b/fastlane/metadata/android/en-US/changelogs/11.txt new file mode 100644 index 0000000..1c37825 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/11.txt @@ -0,0 +1,8 @@ +New features: +- The app is now translated into 6 languages (Chinese (Simplified), English, Hebrew, Hindi, Persian, Ukrainian). You can help translate by going to the app's Weblate page! +- Alarms now use your phone's alarm volume instead of the media volume + +Bug fixes: +- Fixed incorrect calculation of average durations +- Fixed a bug that caused the set session length to not show in the settings slider +- Fixed a bug that caused the focus time on graphs show 0 when it was less than an hour \ No newline at end of file diff --git a/fastlane/metadata/android/hi-IN/short_description.txt b/fastlane/metadata/android/hi-IN/short_description.txt new file mode 100644 index 0000000..1e9457d --- /dev/null +++ b/fastlane/metadata/android/hi-IN/short_description.txt @@ -0,0 +1 @@ +सरल पोमोडोरो टाइमर diff --git a/fastlane/metadata/android/uk/full_description.txt b/fastlane/metadata/android/uk/full_description.txt new file mode 100644 index 0000000..5c73fb5 --- /dev/null +++ b/fastlane/metadata/android/uk/full_description.txt @@ -0,0 +1 @@ +

Tomato - мінімалістичний Pomodoro таймер для Android на базі Material 3 Expressive.


Особливості:

diff --git a/fastlane/metadata/android/uk/short_description.txt b/fastlane/metadata/android/uk/short_description.txt new file mode 100644 index 0000000..16e4d1c --- /dev/null +++ b/fastlane/metadata/android/uk/short_description.txt @@ -0,0 +1 @@ +Мінімалістичний Pomodoro таймер diff --git a/fastlane/metadata/android/uk/title.txt b/fastlane/metadata/android/uk/title.txt new file mode 100644 index 0000000..ee64617 --- /dev/null +++ b/fastlane/metadata/android/uk/title.txt @@ -0,0 +1 @@ +Tomato diff --git a/fastlane/metadata/android/zh-CN/full_description.txt b/fastlane/metadata/android/zh-CN/full_description.txt new file mode 100644 index 0000000..08a5f6c --- /dev/null +++ b/fastlane/metadata/android/zh-CN/full_description.txt @@ -0,0 +1 @@ +

Tomato 是一个基于Material 3 Expressive的安卓极简主义番茄钟.


功能:

diff --git a/fastlane/metadata/android/zh-CN/short_description.txt b/fastlane/metadata/android/zh-CN/short_description.txt new file mode 100644 index 0000000..7cbbd96 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/short_description.txt @@ -0,0 +1 @@ +极简主义番茄钟