Compare commits

..

15 Commits

Author SHA1 Message Date
5176331e84 Version 2.2.2-beta5 2021-01-11 01:34:38 +01:00
65f83caeb5 Merge pull request #267 from Moutony/patch-27
French v2.2.2 (120)
2021-01-11 01:33:22 +01:00
60e8c267bf Version 2.2.2-beta4 2021-01-11 01:32:29 +01:00
10a3204808 Fix #263 2021-01-11 01:30:31 +01:00
98c509ef27 French v2.2.2 (120) 2021-01-10 19:06:20 +01:00
ab1df499af beta version 2.2.2-beta3 2021-01-10 18:02:44 +01:00
ed9a4042c8 Fix #259 2021-01-10 17:56:48 +01:00
a102776214 Merge branch 'master' of github.com:tommasoberlose/another-widget into develop 2021-01-10 17:21:34 +01:00
0778ad4df5 Merge pull request #264 from Drumber/translation
Update German strings.xml
2021-01-10 17:21:27 +01:00
8dce8a74b3 Fix #242 2021-01-10 17:20:52 +01:00
24bb811f93 Fix update calendar service 2021-01-10 15:54:54 +01:00
0500e8d8e8 Update strings.xml
Added missing translations
2021-01-10 14:16:19 +01:00
d2087d094f Beta version 2.2.2-beta1 2021-01-10 12:52:20 +01:00
34fb35f2ab Fix #262 2021-01-10 12:48:17 +01:00
108ecdece0 Update transitions 2021-01-10 02:08:15 +01:00
63 changed files with 923 additions and 359 deletions

Binary file not shown.

View File

@ -22,8 +22,8 @@ android {
applicationId "com.tommasoberlose.anotherwidget" applicationId "com.tommasoberlose.anotherwidget"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 30 targetSdkVersion 30
versionCode 118 versionCode 123
versionName "2.2.1" versionName "2.2.2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY']) buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY'])

View File

@ -40,7 +40,7 @@
<activity android:name=".ui.activities.settings.IntegrationsActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.settings.IntegrationsActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.tabs.MusicPlayersFilterActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.tabs.MusicPlayersFilterActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.tabs.AppNotificationsFilterActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" /> <activity android:name=".ui.activities.tabs.AppNotificationsFilterActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
<activity android:name=".ui.activities.tabs.MediaInfoFormatActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
<receiver android:name=".ui.widgets.MainWidget"> <receiver android:name=".ui.widgets.MainWidget">
<intent-filter> <intent-filter>
@ -150,9 +150,10 @@
</receiver> </receiver>
<service <service
android:name=".services.UpdateCalendarJob" android:name=".services.UpdateCalendarService"
android:permission="android.permission.BIND_JOB_SERVICE" android:enabled="true"
android:exported="true"/> android:exported="false"
android:foregroundServiceType="dataSync" />
<service <service
android:name=".services.LocationService" android:name=".services.LocationService"
android:enabled="true" android:enabled="true"

View File

@ -30,6 +30,7 @@ import com.tommasoberlose.anotherwidget.helpers.GreetingsHelper
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
import com.tommasoberlose.anotherwidget.ui.activities.tabs.AppNotificationsFilterActivity import com.tommasoberlose.anotherwidget.ui.activities.tabs.AppNotificationsFilterActivity
import com.tommasoberlose.anotherwidget.ui.activities.tabs.MediaInfoFormatActivity
import com.tommasoberlose.anotherwidget.ui.activities.tabs.MusicPlayersFilterActivity import com.tommasoberlose.anotherwidget.ui.activities.tabs.MusicPlayersFilterActivity
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
@ -68,11 +69,16 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
/* SONG */ /* SONG */
binding.actionFilterMusicPlayers.isVisible = provider == Constants.GlanceProviderId.PLAYING_SONG binding.actionFilterMusicPlayers.isVisible = provider == Constants.GlanceProviderId.PLAYING_SONG
binding.actionChangeMediaInfoFormat.isVisible = provider == Constants.GlanceProviderId.PLAYING_SONG
if (provider == Constants.GlanceProviderId.PLAYING_SONG) { if (provider == Constants.GlanceProviderId.PLAYING_SONG) {
binding.actionFilterMusicPlayers.setOnClickListener { binding.actionFilterMusicPlayers.setOnClickListener {
dismiss() dismiss()
context.startActivityForResult(Intent(context, MusicPlayersFilterActivity::class.java), 0) context.startActivityForResult(Intent(context, MusicPlayersFilterActivity::class.java), 0)
} }
binding.actionChangeMediaInfoFormat.setOnClickListener {
dismiss()
context.startActivityForResult(Intent(context, MediaInfoFormatActivity::class.java), 0)
}
checkNotificationPermission() checkNotificationPermission()
} }

View File

@ -4,6 +4,8 @@ import android.os.Build
import androidx.appcompat.app.AppCompatDelegate.* import androidx.appcompat.app.AppCompatDelegate.*
import androidx.core.os.ConfigurationCompat import androidx.core.os.ConfigurationCompat
import com.chibatching.kotpref.KotprefModel import com.chibatching.kotpref.KotprefModel
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.utils.isMetric import com.tommasoberlose.anotherwidget.utils.isMetric
import java.util.* import java.util.*
@ -133,11 +135,11 @@ object Preferences : KotprefModel() {
var lastNotificationPackage by stringPref(default = "") var lastNotificationPackage by stringPref(default = "")
var showMusic by booleanPref(default = false) var showMusic by booleanPref(default = false)
var mediaInfoFormat by stringPref(default = "") var mediaInfoFormat by stringPref(default = MediaPlayerHelper.DEFAULT_MEDIA_INFO_FORMAT)
var mediaPlayerTitle by stringPref(default = "") var mediaPlayerTitle by stringPref(default = "")
var mediaPlayerAlbum by stringPref(default = "") var mediaPlayerAlbum by stringPref(default = "")
var mediaPlayerArtist by stringPref(default = "") var mediaPlayerArtist by stringPref(default = "")
var mediaPlayerPackage by stringPref(default = "") var mediaPlayerPackage by stringPref(default = IntentHelper.DO_NOTHING_OPTION)
var musicPlayersFilter by stringPref(default = "") var musicPlayersFilter by stringPref(default = "")
var appNotificationsFilter by stringPref(default = "") var appNotificationsFilter by stringPref(default = "")

View File

@ -1,29 +1,16 @@
package com.tommasoberlose.anotherwidget.helpers package com.tommasoberlose.anotherwidget.helpers
import android.Manifest import android.Manifest
import android.app.job.JobInfo
import android.app.job.JobParameters
import android.app.job.JobScheduler
import android.app.job.JobService
import android.content.ComponentName
import android.content.ContentUris
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.provider.CalendarContract import android.provider.CalendarContract
import android.util.Log
import com.tommasoberlose.anotherwidget.services.EventListenerJob import com.tommasoberlose.anotherwidget.services.EventListenerJob
import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.models.Event import com.tommasoberlose.anotherwidget.models.Event
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver import com.tommasoberlose.anotherwidget.services.UpdateCalendarService
import com.tommasoberlose.anotherwidget.services.UpdateCalendarJob
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import me.everything.providers.android.calendar.CalendarProvider import me.everything.providers.android.calendar.CalendarProvider
import org.greenrobot.eventbus.EventBus
import java.util.* import java.util.*
import kotlin.Comparator
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
/** /**
@ -32,7 +19,7 @@ import kotlin.collections.ArrayList
object CalendarHelper { object CalendarHelper {
fun updateEventList(context: Context) { fun updateEventList(context: Context) {
UpdateCalendarJob.enqueueWork(context, Intent()) UpdateCalendarService.enqueueWork(context)
} }
fun getCalendarList(context: Context): List<me.everything.providers.android.calendar.Calendar> { fun getCalendarList(context: Context): List<me.everything.providers.android.calendar.Calendar> {

View File

@ -21,6 +21,10 @@ import java.util.*
object IntentHelper { object IntentHelper {
const val DEFAULT_OPTION = ""
const val DO_NOTHING_OPTION = "DO_NOTHING"
const val REFRESH_WIDGET_OPTION = "REFRESH_WIDGET"
fun getWidgetUpdateIntent(context: Context): Intent { fun getWidgetUpdateIntent(context: Context): Intent {
val widgetManager = AppWidgetManager.getInstance(context) val widgetManager = AppWidgetManager.getInstance(context)
val widgetComponent = ComponentName(context, MainWidget::class.java) val widgetComponent = ComponentName(context, MainWidget::class.java)
@ -47,7 +51,7 @@ object IntentHelper {
fun getWeatherIntent(context: Context): Intent { fun getWeatherIntent(context: Context): Intent {
return when (Preferences.weatherAppPackage) { return when (Preferences.weatherAppPackage) {
"" -> { DEFAULT_OPTION -> {
Intent(Intent.ACTION_VIEW).apply { Intent(Intent.ACTION_VIEW).apply {
addCategory(Intent.CATEGORY_DEFAULT) addCategory(Intent.CATEGORY_DEFAULT)
flags = Intent.FLAG_ACTIVITY_NEW_TASK flags = Intent.FLAG_ACTIVITY_NEW_TASK
@ -55,9 +59,12 @@ object IntentHelper {
component = ComponentName("com.google.android.googlequicksearchbox", "com.google.android.apps.gsa.velour.DynamicActivityTrampoline") component = ComponentName("com.google.android.googlequicksearchbox", "com.google.android.apps.gsa.velour.DynamicActivityTrampoline")
} }
} }
"_" -> { DO_NOTHING_OPTION -> {
Intent() Intent()
} }
REFRESH_WIDGET_OPTION -> {
getWidgetUpdateIntent(context)
}
else -> { else -> {
val pm: PackageManager = context.packageManager val pm: PackageManager = context.packageManager
try { try {
@ -79,14 +86,17 @@ object IntentHelper {
.appendPath(Calendar.getInstance().timeInMillis.toString()) .appendPath(Calendar.getInstance().timeInMillis.toString())
.build() .build()
return when (Preferences.calendarAppPackage) { return when (Preferences.calendarAppPackage) {
"" -> { DEFAULT_OPTION -> {
Intent(Intent.ACTION_VIEW).apply { Intent(Intent.ACTION_VIEW).apply {
data = calendarUri data = calendarUri
} }
} }
"_" -> { DO_NOTHING_OPTION -> {
Intent() Intent()
} }
REFRESH_WIDGET_OPTION -> {
getWidgetUpdateIntent(context)
}
else -> { else -> {
val pm: PackageManager = context.packageManager val pm: PackageManager = context.packageManager
try { try {
@ -164,14 +174,17 @@ object IntentHelper {
fun getClockIntent(context: Context): Intent { fun getClockIntent(context: Context): Intent {
return when (Preferences.clockAppPackage) { return when (Preferences.clockAppPackage) {
"" -> { DEFAULT_OPTION -> {
Intent(AlarmClock.ACTION_SHOW_ALARMS).apply { Intent(AlarmClock.ACTION_SHOW_ALARMS).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK flags = Intent.FLAG_ACTIVITY_NEW_TASK
} }
} }
"_" -> { DO_NOTHING_OPTION -> {
Intent() Intent()
} }
REFRESH_WIDGET_OPTION -> {
getWidgetUpdateIntent(context)
}
else -> { else -> {
val pm: PackageManager = context.packageManager val pm: PackageManager = context.packageManager
try { try {
@ -191,7 +204,7 @@ object IntentHelper {
fun getMusicIntent(context: Context): Intent { fun getMusicIntent(context: Context): Intent {
return when (Preferences.mediaPlayerPackage) { return when (Preferences.mediaPlayerPackage) {
"" -> { DO_NOTHING_OPTION -> {
Intent() Intent()
} }
else -> { else -> {

View File

@ -15,14 +15,32 @@ import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import java.lang.Exception import java.lang.Exception
object MediaPlayerHelper { object MediaPlayerHelper {
const val MEDIA_INFO_TITLE = "%TITLE"
const val MEDIA_INFO_ARTIST = "%ARTIST"
const val MEDIA_INFO_ALBUM = "%ALBUM"
const val DEFAULT_MEDIA_INFO_FORMAT = "%TITLE, %ARTIST"
fun isSomeonePlaying(context: Context) = Preferences.showMusic && ActiveNotificationsHelper.checkNotificationAccess(context) && Preferences.mediaPlayerTitle != "" fun isSomeonePlaying(context: Context) = Preferences.showMusic && ActiveNotificationsHelper.checkNotificationAccess(context) && Preferences.mediaPlayerTitle != ""
fun getMediaInfo(): String { fun getMediaInfo(format: String = Preferences.mediaInfoFormat, title: String = Preferences.mediaPlayerTitle, artist: String = Preferences.mediaPlayerArtist, album: String = Preferences.mediaPlayerAlbum): String {
return if (Preferences.mediaPlayerArtist == "") { return when (format) {
Preferences.mediaPlayerTitle "",
} else { DEFAULT_MEDIA_INFO_FORMAT -> {
"%s, %s".format(Preferences.mediaPlayerTitle, Preferences.mediaPlayerArtist) if (Preferences.mediaPlayerArtist == "") {
} Preferences.mediaPlayerTitle
} else {
DEFAULT_MEDIA_INFO_FORMAT.replace(MEDIA_INFO_TITLE, title)
.replace(MEDIA_INFO_ARTIST, artist)
.replace(MEDIA_INFO_ALBUM, album)
}
}
else -> {
format.replace(MEDIA_INFO_TITLE, title)
.replace(MEDIA_INFO_ARTIST, artist)
.replace(MEDIA_INFO_ALBUM, album)
}
}
} }
fun updatePlayingMediaInfo(context: Context) { fun updatePlayingMediaInfo(context: Context) {

View File

@ -63,10 +63,20 @@ object SettingsStringHelper {
} }
fun getVariantLabel(context: Context, variant: String): String = when { fun getVariantLabel(context: Context, variant: String): String = when {
variant == "italic" -> context.getString(R.string.font_italic)
variant.contains("100") && variant.contains("italic") -> context.getString(R.string.font_100_italic)
variant.contains("200") && variant.contains("italic") -> context.getString(R.string.font_200_italic)
variant.contains("300") && variant.contains("italic") -> context.getString(R.string.font_300_italic)
variant.contains("400") && variant.contains("italic") -> context.getString(R.string.font_400_italic)
variant.contains("500") && variant.contains("italic") -> context.getString(R.string.font_500_italic)
variant.contains("600") && variant.contains("italic") -> context.getString(R.string.font_600_italic)
variant.contains("700") && variant.contains("italic") -> context.getString(R.string.font_700_italic)
variant.contains("800") && variant.contains("italic") -> context.getString(R.string.font_800_italic)
variant.contains("900") && variant.contains("italic") -> context.getString(R.string.font_900_italic)
variant == "regular" || variant.contains("400") -> context.getString(R.string.font_400)
variant.contains("100") -> context.getString(R.string.font_100) variant.contains("100") -> context.getString(R.string.font_100)
variant.contains("200") -> context.getString(R.string.font_200) variant.contains("200") -> context.getString(R.string.font_200)
variant.contains("300") -> context.getString(R.string.font_300) variant.contains("300") -> context.getString(R.string.font_300)
variant.contains("regular") || variant.contains("400") -> context.getString(R.string.font_400)
variant.contains("500") -> context.getString(R.string.font_500) variant.contains("500") -> context.getString(R.string.font_500)
variant.contains("600") -> context.getString(R.string.font_600) variant.contains("600") -> context.getString(R.string.font_600)
variant.contains("700") -> context.getString(R.string.font_700) variant.contains("700") -> context.getString(R.string.font_700)

View File

@ -2,6 +2,7 @@ package com.tommasoberlose.anotherwidget.network
import android.content.Context import android.content.Context
import android.util.Log import android.util.Log
import com.chibatching.kotpref.Kotpref
import com.google.gson.internal.LinkedTreeMap import com.google.gson.internal.LinkedTreeMap
import com.haroldadmin.cnradapter.NetworkResponse import com.haroldadmin.cnradapter.NetworkResponse
import com.haroldadmin.cnradapter.executeWithRetry import com.haroldadmin.cnradapter.executeWithRetry
@ -26,6 +27,7 @@ import java.util.*
class WeatherNetworkApi(val context: Context) { class WeatherNetworkApi(val context: Context) {
suspend fun updateWeather() { suspend fun updateWeather() {
Kotpref.init(context)
Preferences.weatherProviderError = "-" Preferences.weatherProviderError = "-"
Preferences.weatherProviderLocationError = "" Preferences.weatherProviderLocationError = ""

View File

@ -26,7 +26,7 @@ import kotlin.collections.ArrayList
class LocationService : Service() { class LocationService : Service() {
private val jobs: ArrayList<Job> = ArrayList() private var job: Job? = null
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
@ -34,13 +34,13 @@ class LocationService : Service() {
} }
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (ActivityCompat.checkSelfPermission( job?.cancel()
this, job = GlobalScope.launch(Dispatchers.IO) {
Manifest.permission.ACCESS_FINE_LOCATION if (ActivityCompat.checkSelfPermission(
) == PackageManager.PERMISSION_GRANTED this@LocationService,
) { Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
jobs += GlobalScope.launch(Dispatchers.IO) { ) {
LocationServices.getFusedLocationProviderClient(this@LocationService).lastLocation.addOnCompleteListener { task -> LocationServices.getFusedLocationProviderClient(this@LocationService).lastLocation.addOnCompleteListener { task ->
val networkApi = WeatherNetworkApi(this@LocationService) val networkApi = WeatherNetworkApi(this@LocationService)
if (task.isSuccessful) { if (task.isSuccessful) {
@ -67,18 +67,17 @@ class LocationService : Service() {
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent()) EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} }
} }
} else {
stopSelf()
} }
} else {
stopSelf()
} }
return START_STICKY return START_STICKY
} }
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
jobs.forEach { job?.cancel()
it.cancel() job = null
}
} }
companion object { companion object {
@ -116,7 +115,6 @@ class LocationService : Service() {
val builder = NotificationCompat.Builder(this@LocationService, getString(R.string.location_access_notification_channel_id)) val builder = NotificationCompat.Builder(this@LocationService, getString(R.string.location_access_notification_channel_id))
.setSmallIcon(R.drawable.ic_stat_notification) .setSmallIcon(R.drawable.ic_stat_notification)
.setContentTitle(getString(R.string.location_access_notification_title)) .setContentTitle(getString(R.string.location_access_notification_title))
.setStyle(NotificationCompat.BigTextStyle().bigText(getString(R.string.location_access_notification_subtitle)))
.setOngoing(true) .setOngoing(true)
.setColor(ContextCompat.getColor(this@LocationService, R.color.colorAccent)) .setColor(ContextCompat.getColor(this@LocationService, R.color.colorAccent))

View File

@ -1,153 +0,0 @@
package com.tommasoberlose.anotherwidget.services
import android.Manifest
import android.content.Context
import android.content.Intent
import android.provider.CalendarContract
import android.util.Log
import androidx.core.app.JobIntentService
import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.applyFilters
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.sortEvents
import com.tommasoberlose.anotherwidget.models.Event
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import me.everything.providers.android.calendar.CalendarProvider
import org.greenrobot.eventbus.EventBus
import java.util.*
import kotlin.Comparator
import kotlin.collections.ArrayList
class UpdateCalendarJob : JobIntentService() {
companion object {
private const val jobId = 1200
fun enqueueWork(context: Context, work: Intent) {
enqueueWork(context, UpdateCalendarJob::class.java, jobId, work)
}
}
override fun onHandleWork(intent: Intent) {
val eventRepository = EventRepository(this)
if (Preferences.showEvents) {
val eventList = ArrayList<Event>()
val now = Calendar.getInstance()
val begin = Calendar.getInstance().apply {
set(Calendar.MILLISECOND, 0)
set(Calendar.SECOND, 0)
set(Calendar.MINUTE, 0)
set(Calendar.HOUR_OF_DAY, 0)
}
val limit = Calendar.getInstance().apply {
when (Preferences.showUntil) {
0 -> add(Calendar.HOUR, 3)
1 -> add(Calendar.HOUR, 6)
2 -> add(Calendar.HOUR, 12)
3 -> add(Calendar.DAY_OF_MONTH, 1)
4 -> add(Calendar.DAY_OF_MONTH, 3)
5 -> add(Calendar.DAY_OF_MONTH, 7)
6 -> add(Calendar.MINUTE, 30)
7 -> add(Calendar.HOUR, 1)
else -> add(Calendar.HOUR, 6)
}
}
if (!checkGrantedPermission(
Manifest.permission.READ_CALENDAR
)
) {
eventRepository.resetNextEventData()
} else {
try {
val provider = CalendarProvider(this)
val data = provider.getInstances(begin.timeInMillis, limit.timeInMillis)
if (data != null) {
val instances = data.list
for (instance in instances) {
try {
val e = provider.getEvent(instance.eventId)
if (e != null && !e.deleted && instance.begin <= limit.timeInMillis && now.timeInMillis < instance.end && !CalendarHelper.getFilteredCalendarIdList()
.contains(e.calendarId)
) {
if (e.allDay) {
val start = Calendar.getInstance()
start.timeInMillis = instance.begin
val end = Calendar.getInstance()
end.timeInMillis = instance.end
instance.begin =
start.timeInMillis - start.timeZone.getOffset(start.timeInMillis)
instance.end =
end.timeInMillis - end.timeZone.getOffset(end.timeInMillis)
}
// Check all day events
val startDate = Calendar.getInstance()
startDate.timeInMillis = instance.begin
val endDate = Calendar.getInstance()
endDate.timeInMillis = instance.end
val isAllDay = e.allDay || (
startDate.get(Calendar.MILLISECOND) == 0
&& startDate.get(Calendar.SECOND) == 0
&& startDate.get(Calendar.MINUTE) == 0
&& startDate.get(Calendar.HOUR_OF_DAY) == 0
&& endDate.get(Calendar.MILLISECOND) == 0
&& endDate.get(Calendar.SECOND) == 0
&& endDate.get(Calendar.MINUTE) == 0
&& endDate.get(Calendar.HOUR_OF_DAY) == 0
)
eventList.add(
Event(
id = instance.id,
eventID = e.id,
title = e.title ?: "",
startDate = instance.begin,
endDate = instance.end,
calendarID = e.calendarId.toInt(),
allDay = isAllDay,
address = e.eventLocation ?: "",
selfAttendeeStatus = e.selfAttendeeStatus.toInt(),
availability = e.availability
)
)
}
} catch (ignored: Exception) {
}
}
}
val sortedEvents = eventList.sortEvents()
val filteredEventList = sortedEvents
.applyFilters()
if (filteredEventList.isEmpty()) {
eventRepository.resetNextEventData()
eventRepository.clearEvents()
} else {
eventRepository.saveEvents(
sortedEvents
)
eventRepository.saveNextEventData(filteredEventList.first())
}
} catch (ignored: java.lang.Exception) {
}
}
} else {
eventRepository.resetNextEventData()
}
UpdatesReceiver.setUpdates(this)
MainWidget.updateWidget(this)
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
eventRepository.close()
}
}

View File

@ -0,0 +1,218 @@
package com.tommasoberlose.anotherwidget.services
import android.Manifest
import android.app.*
import android.content.Context
import android.content.Intent
import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.applyFilters
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.sortEvents
import com.tommasoberlose.anotherwidget.models.Event
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import me.everything.providers.android.calendar.CalendarProvider
import org.greenrobot.eventbus.EventBus
import java.util.*
import kotlin.collections.ArrayList
class UpdateCalendarService : Service() {
companion object {
const val CALENDAR_SYNC_NOTIFICATION_ID = 28466
fun enqueueWork(context: Context) {
context.startService(Intent(context, UpdateCalendarService::class.java))
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
context.startForegroundService(Intent(context, UpdateCalendarService::class.java))
} else {
context.startService(Intent(context, UpdateCalendarService::class.java))
}
}
}
override fun onCreate() {
super.onCreate()
startForeground(CALENDAR_SYNC_NOTIFICATION_ID, getCalendarSyncNotification())
}
private var job: Job? = null
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
job?.cancel()
job = GlobalScope.launch(Dispatchers.IO) {
val eventRepository = EventRepository(this@UpdateCalendarService)
if (Preferences.showEvents) {
val eventList = ArrayList<Event>()
val now = Calendar.getInstance()
val begin = Calendar.getInstance().apply {
set(Calendar.MILLISECOND, 0)
set(Calendar.SECOND, 0)
set(Calendar.MINUTE, 0)
set(Calendar.HOUR_OF_DAY, 0)
}
val limit = Calendar.getInstance().apply {
when (Preferences.showUntil) {
0 -> add(Calendar.HOUR, 3)
1 -> add(Calendar.HOUR, 6)
2 -> add(Calendar.HOUR, 12)
3 -> add(Calendar.DAY_OF_MONTH, 1)
4 -> add(Calendar.DAY_OF_MONTH, 3)
5 -> add(Calendar.DAY_OF_MONTH, 7)
6 -> add(Calendar.MINUTE, 30)
7 -> add(Calendar.HOUR, 1)
else -> add(Calendar.HOUR, 6)
}
}
if (!checkGrantedPermission(
Manifest.permission.READ_CALENDAR
)
) {
eventRepository.resetNextEventData()
} else {
try {
val provider = CalendarProvider(this@UpdateCalendarService)
val data = provider.getInstances(begin.timeInMillis, limit.timeInMillis)
if (data != null) {
val instances = data.list
for (instance in instances) {
try {
val e = provider.getEvent(instance.eventId)
if (e != null && !e.deleted && instance.begin <= limit.timeInMillis && now.timeInMillis < instance.end && !CalendarHelper.getFilteredCalendarIdList()
.contains(e.calendarId)
) {
if (e.allDay) {
val start = Calendar.getInstance()
start.timeInMillis = instance.begin
val end = Calendar.getInstance()
end.timeInMillis = instance.end
instance.begin =
start.timeInMillis - start.timeZone.getOffset(start.timeInMillis)
instance.end =
end.timeInMillis - end.timeZone.getOffset(end.timeInMillis)
}
// Check all day events
val startDate = Calendar.getInstance()
startDate.timeInMillis = instance.begin
val endDate = Calendar.getInstance()
endDate.timeInMillis = instance.end
val isAllDay = e.allDay || (
startDate.get(Calendar.MILLISECOND) == 0
&& startDate.get(Calendar.SECOND) == 0
&& startDate.get(Calendar.MINUTE) == 0
&& startDate.get(Calendar.HOUR_OF_DAY) == 0
&& endDate.get(Calendar.MILLISECOND) == 0
&& endDate.get(Calendar.SECOND) == 0
&& endDate.get(Calendar.MINUTE) == 0
&& endDate.get(Calendar.HOUR_OF_DAY) == 0
)
eventList.add(
Event(
id = instance.id,
eventID = e.id,
title = e.title ?: "",
startDate = instance.begin,
endDate = instance.end,
calendarID = e.calendarId.toInt(),
allDay = isAllDay,
address = e.eventLocation ?: "",
selfAttendeeStatus = e.selfAttendeeStatus.toInt(),
availability = e.availability
)
)
}
} catch (ignored: Exception) {
}
}
}
val sortedEvents = eventList.sortEvents()
val filteredEventList = sortedEvents
.applyFilters()
if (filteredEventList.isEmpty()) {
eventRepository.resetNextEventData()
eventRepository.clearEvents()
} else {
eventRepository.saveEvents(
sortedEvents
)
eventRepository.saveNextEventData(filteredEventList.first())
}
} catch (ignored: java.lang.Exception) {
}
}
} else {
eventRepository.resetNextEventData()
}
UpdatesReceiver.setUpdates(this@UpdateCalendarService)
MainWidget.updateWidget(this@UpdateCalendarService)
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
eventRepository.close()
stopSelf()
}
return START_STICKY
}
override fun onDestroy() {
super.onDestroy()
job?.cancel()
job = null
}
private fun getCalendarSyncNotification(): Notification {
with(NotificationManagerCompat.from(this)) {
// Create channel
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
createNotificationChannel(
NotificationChannel(
getString(R.string.calendar_sync_notification_channel_id),
getString(R.string.calendar_sync_notification_channel_name),
NotificationManager.IMPORTANCE_LOW
).apply {
description = getString(R.string.calendar_sync_notification_channel_description)
}
)
}
val builder = NotificationCompat.Builder(this@UpdateCalendarService, getString(R.string.calendar_sync_notification_channel_id))
.setSmallIcon(R.drawable.ic_stat_notification)
.setContentTitle(getString(R.string.calendar_sync_notification_title))
.setOngoing(true)
.setColor(ContextCompat.getColor(this@UpdateCalendarService, R.color.colorAccent))
// Main intent that open the activity
builder.setContentIntent(PendingIntent.getActivity(this@UpdateCalendarService, 0, Intent(this@UpdateCalendarService, MainActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT))
return builder.build()
}
}
}

View File

@ -4,6 +4,7 @@ import android.Manifest
import android.app.Activity import android.app.Activity
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
@ -22,9 +23,10 @@ import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.global.RequestCode import com.tommasoberlose.anotherwidget.global.RequestCode
import com.tommasoberlose.anotherwidget.ui.activities.tabs.WeatherProviderActivity import com.tommasoberlose.anotherwidget.ui.activities.tabs.WeatherProviderActivity
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceChangeListener {
private var mAppWidgetId: Int = -1 private var mAppWidgetId: Int = -1
private lateinit var viewModel: MainViewModel private lateinit var viewModel: MainViewModel
@ -140,4 +142,18 @@ class MainActivity : AppCompatActivity() {
Preferences.showEvents = false Preferences.showEvents = false
} }
} }
override fun onStart() {
Preferences.preferences.registerOnSharedPreferenceChangeListener(this)
super.onStart()
}
override fun onStop() {
super.onStop()
Preferences.preferences.unregisterOnSharedPreferenceChangeListener(this)
}
override fun onSharedPreferenceChanged(p0: SharedPreferences?, p1: String?) {
MainWidget.updateWidget(this)
}
} }

View File

@ -15,8 +15,10 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.google.android.material.card.MaterialCardView
import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding
import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
import com.tommasoberlose.anotherwidget.ui.viewmodels.tabs.ChooseApplicationViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.tabs.ChooseApplicationViewModel
import kotlinx.coroutines.* import kotlinx.coroutines.*
import net.idik.lib.slimadapter.SlimAdapter import net.idik.lib.slimadapter.SlimAdapter
@ -29,9 +31,13 @@ class ChooseApplicationActivity : AppCompatActivity() {
private lateinit var viewModel: ChooseApplicationViewModel private lateinit var viewModel: ChooseApplicationViewModel
private lateinit var binding: ActivityChooseApplicationBinding private lateinit var binding: ActivityChooseApplicationBinding
private var selectedPackage: String? = null
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
selectedPackage = intent.extras?.getString(Constants.RESULT_APP_PACKAGE)
viewModel = ViewModelProvider(this).get(ChooseApplicationViewModel::class.java) viewModel = ViewModelProvider(this).get(ChooseApplicationViewModel::class.java)
binding = ActivityChooseApplicationBinding.inflate(layoutInflater) binding = ActivityChooseApplicationBinding.inflate(layoutInflater)
@ -41,21 +47,71 @@ class ChooseApplicationActivity : AppCompatActivity() {
adapter = SlimAdapterEx.create() adapter = SlimAdapterEx.create()
adapter adapter
.register<String>(R.layout.application_info_layout) { _, injector -> .register<String>(R.layout.application_info_layout) { item, injector ->
injector when (item) {
.text(R.id.text, getString(R.string.default_name)) IntentHelper.DO_NOTHING_OPTION -> {
.image(R.id.icon, R.drawable.round_add_to_home_screen_24) injector
.with<ImageView>(R.id.icon) { .text(R.id.text, getString(R.string.gestures_do_nothing))
it.scaleX = 0.8f .image(R.id.icon, R.drawable.round_no_cell_24)
it.scaleY = 0.8f .with<ImageView>(R.id.icon) {
it.setColorFilter(ContextCompat.getColor(this, R.color.colorPrimaryText), android.graphics.PorterDuff.Mode.MULTIPLY) it.scaleX = 0.8f
it.scaleY = 0.8f
it.setColorFilter(ContextCompat.getColor(this, R.color.colorPrimaryText), android.graphics.PorterDuff.Mode.MULTIPLY)
}
.clicked(R.id.item) {
val resultIntent = Intent()
resultIntent.putExtra(Constants.RESULT_APP_NAME, IntentHelper.DO_NOTHING_OPTION)
resultIntent.putExtra(Constants.RESULT_APP_PACKAGE, IntentHelper.DO_NOTHING_OPTION)
setResult(Activity.RESULT_OK, resultIntent)
finish()
}
.with<MaterialCardView>(R.id.item) {
it.strokeColor = ContextCompat.getColor(this, if (selectedPackage == IntentHelper.DO_NOTHING_OPTION) R.color.colorAccent else R.color.cardBorder)
it.setCardBackgroundColor(ContextCompat.getColor(this, if (selectedPackage == IntentHelper.DO_NOTHING_OPTION) R.color.colorAccent_op10 else R.color.colorPrimaryDark))
}
}
IntentHelper.REFRESH_WIDGET_OPTION -> {
injector
.text(R.id.text, getString(R.string.action_refresh_widget))
.image(R.id.icon, R.drawable.round_refresh)
.with<ImageView>(R.id.icon) {
it.scaleX = 0.8f
it.scaleY = 0.8f
it.setColorFilter(ContextCompat.getColor(this, R.color.colorPrimaryText), android.graphics.PorterDuff.Mode.MULTIPLY)
}
.clicked(R.id.item) {
val resultIntent = Intent()
resultIntent.putExtra(Constants.RESULT_APP_NAME, IntentHelper.REFRESH_WIDGET_OPTION)
resultIntent.putExtra(Constants.RESULT_APP_PACKAGE, IntentHelper.REFRESH_WIDGET_OPTION)
setResult(Activity.RESULT_OK, resultIntent)
finish()
}
.with<MaterialCardView>(R.id.item) {
it.strokeColor = ContextCompat.getColor(this, if (selectedPackage == IntentHelper.REFRESH_WIDGET_OPTION) R.color.colorAccent else R.color.cardBorder)
it.setCardBackgroundColor(ContextCompat.getColor(this, if (selectedPackage == IntentHelper.REFRESH_WIDGET_OPTION) R.color.colorAccent_op10 else R.color.colorPrimaryDark))
}
}
else -> {
injector
.text(R.id.text, getString(R.string.default_name))
.image(R.id.icon, R.drawable.round_add_to_home_screen_24)
.with<ImageView>(R.id.icon) {
it.scaleX = 0.8f
it.scaleY = 0.8f
it.setColorFilter(ContextCompat.getColor(this, R.color.colorPrimaryText), android.graphics.PorterDuff.Mode.MULTIPLY)
}
.clicked(R.id.item) {
val resultIntent = Intent()
resultIntent.putExtra(Constants.RESULT_APP_NAME, IntentHelper.DEFAULT_OPTION)
resultIntent.putExtra(Constants.RESULT_APP_PACKAGE, IntentHelper.DEFAULT_OPTION)
setResult(Activity.RESULT_OK, resultIntent)
finish()
}
.with<MaterialCardView>(R.id.item) {
it.strokeColor = ContextCompat.getColor(this, if (selectedPackage == IntentHelper.DEFAULT_OPTION) R.color.colorAccent else R.color.cardBorder)
it.setCardBackgroundColor(ContextCompat.getColor(this, if (selectedPackage == IntentHelper.DEFAULT_OPTION) R.color.colorAccent_op10 else R.color.colorPrimaryDark))
}
} }
.clicked(R.id.item) {
val resultIntent = Intent()
resultIntent.putExtra(Constants.RESULT_APP_NAME, "")
resultIntent.putExtra(Constants.RESULT_APP_PACKAGE, "")
setResult(Activity.RESULT_OK, resultIntent)
finish()
} }
} }
.register<ResolveInfo>(R.layout.application_info_layout) { item, injector -> .register<ResolveInfo>(R.layout.application_info_layout) { item, injector ->
@ -68,10 +124,13 @@ class ChooseApplicationActivity : AppCompatActivity() {
.centerCrop() .centerCrop()
.into(it) .into(it)
} }
.clicked(R.id.item) {
injector.clicked(R.id.item) { saveApp(item)
saveApp(item) }
} .with<MaterialCardView>(R.id.item) {
it.strokeColor = ContextCompat.getColor(this, if (selectedPackage == item.activityInfo.packageName) R.color.colorAccent else R.color.cardBorder)
it.setCardBackgroundColor(ContextCompat.getColor(this, if (selectedPackage == item.activityInfo.packageName) R.color.colorAccent_op10 else R.color.colorPrimaryDark))
}
} }
.attachTo(binding.listView) .attachTo(binding.listView)
@ -114,7 +173,7 @@ class ChooseApplicationActivity : AppCompatActivity() {
} }
} }
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
adapter.updateData(listOf("Default") + filteredList) adapter.updateData(listOf(IntentHelper.DO_NOTHING_OPTION, IntentHelper.DEFAULT_OPTION, IntentHelper.REFRESH_WIDGET_OPTION) + filteredList)
binding.loader.visibility = View.INVISIBLE binding.loader.visibility = View.INVISIBLE
} }
} }

View File

@ -22,7 +22,7 @@ import java.lang.Exception
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
class CustomDateActivity : AppCompatActivity() { class CustomDateActivity : AppCompatActivity() {
private lateinit var adapter: SlimAdapter private lateinit var adapter: SlimAdapter
private lateinit var viewModel: CustomDateViewModel private lateinit var viewModel: CustomDateViewModel

View File

@ -6,6 +6,7 @@ import android.graphics.Typeface
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.HandlerThread import android.os.HandlerThread
import android.util.Log
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.TextView import android.widget.TextView
@ -18,6 +19,7 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.chibatching.kotpref.blockingBulk import com.chibatching.kotpref.blockingBulk
import com.google.gson.Gson
import com.koolio.library.Font import com.koolio.library.Font
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
@ -125,7 +127,7 @@ class CustomFontActivity : AppCompatActivity() {
if (item.fontVariants.isEmpty()) { if (item.fontVariants.isEmpty()) {
dialog.addItem(SettingsStringHelper.getVariantLabel(this, "regular"), -1) dialog.addItem(SettingsStringHelper.getVariantLabel(this, "regular"), -1)
} else { } else {
item.fontVariants.filter { !it.contains("italic") } item.fontVariants
.forEachIndexed { index, s -> .forEachIndexed { index, s ->
dialog.addItem(SettingsStringHelper.getVariantLabel(this, s), index) dialog.addItem(SettingsStringHelper.getVariantLabel(this, s), index)
} }

View File

@ -0,0 +1,109 @@
package com.tommasoberlose.anotherwidget.ui.activities.tabs
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.chibatching.kotpref.blockingBulk
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.databinding.ActivityMediaInfoFormatBinding
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.ui.viewmodels.tabs.MediaInfoFormatViewModel
import com.tommasoberlose.anotherwidget.utils.getCapWordString
import com.tommasoberlose.anotherwidget.utils.openURI
import com.tommasoberlose.anotherwidget.utils.toast
import kotlinx.coroutines.*
import net.idik.lib.slimadapter.SlimAdapter
import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.*
class MediaInfoFormatActivity : AppCompatActivity() {
private lateinit var adapter: SlimAdapter
private lateinit var viewModel: MediaInfoFormatViewModel
private lateinit var binding: ActivityMediaInfoFormatBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this).get(MediaInfoFormatViewModel::class.java)
binding = ActivityMediaInfoFormatBinding.inflate(layoutInflater)
binding.listView.setHasFixedSize(true)
val mLayoutManager = LinearLayoutManager(this)
binding.listView.layoutManager = mLayoutManager
adapter = SlimAdapter.create()
adapter
.register<String>(R.layout.custom_date_example_item) { item, injector ->
injector
.text(R.id.custom_date_example_format, item)
.text(
R.id.custom_date_example_value, MediaPlayerHelper.getMediaInfo(item, EXAMPLE_TITLE, EXAMPLE_ARTIST, EXAMPLE_ALBUM))
}
.attachTo(binding.listView)
adapter.updateData(
listOf(
MediaPlayerHelper.MEDIA_INFO_TITLE, MediaPlayerHelper.MEDIA_INFO_ARTIST, MediaPlayerHelper.MEDIA_INFO_ALBUM
)
)
setupListener()
subscribeUi(binding, viewModel)
binding.mediaInfoFormatInput.requestFocus()
setContentView(binding.root)
}
private var formatJob: Job? = null
private fun subscribeUi(binding: ActivityMediaInfoFormatBinding, viewModel: MediaInfoFormatViewModel) {
binding.viewModel = viewModel
binding.lifecycleOwner = this
viewModel.mediaInfoFormatInput.observe(this) { mediaInfoFormatInput ->
formatJob?.cancel()
formatJob = lifecycleScope.launch(Dispatchers.IO) {
withContext(Dispatchers.Main) {
binding.loader.visibility = View.VISIBLE
}
delay(200)
val text = MediaPlayerHelper.getMediaInfo(mediaInfoFormatInput, EXAMPLE_TITLE, EXAMPLE_ARTIST, EXAMPLE_ALBUM)
withContext(Dispatchers.Main) {
binding.loader.visibility = View.INVISIBLE
binding.mediaInfoFormatInputValue.text = text
}
}
}
}
private fun setupListener() {
binding.actionBack.setOnClickListener {
onBackPressed()
}
}
override fun onBackPressed() {
Preferences.blockingBulk {
mediaInfoFormat = viewModel.mediaInfoFormatInput.value ?: ""
}
super.onBackPressed()
}
companion object {
const val EXAMPLE_TITLE = "Thunderstruck"
const val EXAMPLE_ARTIST = "AC/DC"
const val EXAMPLE_ALBUM = "The Razors Edge"
}
}

View File

@ -63,8 +63,8 @@ class MainFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) enterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, false)
} }
override fun onCreateView( override fun onCreateView(
@ -102,9 +102,7 @@ class MainFragment : Fragment() {
} }
binding.actionSettings.setOnClickListener { binding.actionSettings.setOnClickListener {
Navigation.findNavController(it).navigate(R.id.action_appMainFragment_to_appSettingsFragment, null, null, FragmentNavigatorExtras( Navigation.findNavController(it).navigate(R.id.action_appMainFragment_to_appSettingsFragment,)
binding.actionBack to "action_back"
))
} }
binding.preview.layoutParams = binding.preview.layoutParams.apply { binding.preview.layoutParams = binding.preview.layoutParams.apply {

View File

@ -52,9 +52,9 @@ class SettingsFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move) // sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true) enterTransition = MaterialSharedAxis(MaterialSharedAxis.Y, true)
// returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false) returnTransition = MaterialSharedAxis(MaterialSharedAxis.Y, false)
} }
override fun onCreateView( override fun onCreateView(

View File

@ -281,26 +281,6 @@ class CalendarFragment : Fragment() {
} }
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
RequestCode.CALENDAR_APP_REQUEST_CODE.code -> {
Preferences.bulk {
calendarAppName = data?.getStringExtra(Constants.RESULT_APP_NAME) ?: getString(R.string.default_calendar_app)
calendarAppPackage = data?.getStringExtra(Constants.RESULT_APP_PACKAGE) ?: ""
}
}
RequestCode.EVENT_APP_REQUEST_CODE.code -> {
Preferences.bulk {
eventAppName = data?.getStringExtra(Constants.RESULT_APP_NAME) ?: getString(R.string.default_event_app)
eventAppPackage = data?.getStringExtra(Constants.RESULT_APP_PACKAGE) ?: ""
}
}
}
}
super.onActivityResult(requestCode, resultCode, data)
}
private fun maintainScrollPosition(callback: () -> Unit) { private fun maintainScrollPosition(callback: () -> Unit) {
binding.scrollView.isScrollable = false binding.scrollView.isScrollable = false
callback.invoke() callback.invoke()

View File

@ -180,16 +180,6 @@ class ClockFragment : Fragment() {
} }
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK && requestCode == RequestCode.CLOCK_APP_REQUEST_CODE.code) {
Preferences.bulk {
clockAppName = data?.getStringExtra(Constants.RESULT_APP_NAME) ?: getString(R.string.default_clock_app)
clockAppPackage = data?.getStringExtra(Constants.RESULT_APP_PACKAGE) ?: ""
}
}
super.onActivityResult(requestCode, resultCode, data)
}
override fun onResume() { override fun onResume() {
binding.is24Format = DateFormat.is24HourFormat(requireContext()) binding.is24Format = DateFormat.is24HourFormat(requireContext())
super.onResume() super.onResume()

View File

@ -1,6 +1,7 @@
package com.tommasoberlose.anotherwidget.ui.fragments.tabs package com.tommasoberlose.anotherwidget.ui.fragments.tabs
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
@ -12,6 +13,7 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.chibatching.kotpref.blockingBulk import com.chibatching.kotpref.blockingBulk
import com.chibatching.kotpref.bulk
import com.google.android.material.transition.MaterialSharedAxis import com.google.android.material.transition.MaterialSharedAxis
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
@ -30,6 +32,7 @@ import com.tommasoberlose.anotherwidget.ui.activities.tabs.CustomDateActivity
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.activities.tabs.ChooseApplicationActivity import com.tommasoberlose.anotherwidget.ui.activities.tabs.ChooseApplicationActivity
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.isDarkTheme import com.tommasoberlose.anotherwidget.utils.isDarkTheme
import com.tommasoberlose.anotherwidget.utils.isDefaultSet import com.tommasoberlose.anotherwidget.utils.isDefaultSet
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -45,7 +48,6 @@ class GesturesFragment : Fragment() {
} }
private lateinit var viewModel: MainViewModel private lateinit var viewModel: MainViewModel
private lateinit var colors: IntArray
private lateinit var binding: FragmentTabGesturesBinding private lateinit var binding: FragmentTabGesturesBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -97,14 +99,16 @@ class GesturesFragment : Fragment() {
viewModel.calendarAppName.observe(viewLifecycleOwner) { viewModel.calendarAppName.observe(viewLifecycleOwner) {
maintainScrollPosition { maintainScrollPosition {
binding.calendarAppLabel.text = when { binding.calendarAppLabel.text = when {
Preferences.calendarAppName != "" -> Preferences.calendarAppName it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
it == IntentHelper.REFRESH_WIDGET_OPTION -> "None, the widget will be refreshed"
it != IntentHelper.DEFAULT_OPTION -> it
else -> { else -> {
if (IntentHelper.getCalendarIntent(requireContext()).isDefaultSet(requireContext())) { if (IntentHelper.getCalendarIntent(requireContext()).isDefaultSet(requireContext())) {
getString( getString(
R.string.default_calendar_app R.string.default_calendar_app
) )
} else { } else {
getString(R.string.nothing) getString(R.string.gestures_do_nothing)
} }
} }
} }
@ -120,14 +124,16 @@ class GesturesFragment : Fragment() {
viewModel.clockAppName.observe(viewLifecycleOwner) { viewModel.clockAppName.observe(viewLifecycleOwner) {
maintainScrollPosition { maintainScrollPosition {
binding.clockAppLabel.text = when { binding.clockAppLabel.text = when {
Preferences.clockAppName != "" -> Preferences.clockAppName it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
it == IntentHelper.REFRESH_WIDGET_OPTION -> "None, the widget will be refreshed"
it != IntentHelper.DEFAULT_OPTION -> it
else -> { else -> {
if (IntentHelper.getClockIntent(requireContext()).isDefaultSet(requireContext())) { if (IntentHelper.getClockIntent(requireContext()).isDefaultSet(requireContext())) {
getString( getString(
R.string.default_clock_app R.string.default_clock_app
) )
} else { } else {
getString(R.string.nothing) getString(R.string.gestures_do_nothing)
} }
} }
} }
@ -136,8 +142,12 @@ class GesturesFragment : Fragment() {
viewModel.weatherAppName.observe(viewLifecycleOwner) { viewModel.weatherAppName.observe(viewLifecycleOwner) {
maintainScrollPosition { maintainScrollPosition {
binding.weatherAppLabel.text = binding.weatherAppLabel.text = when {
if (it != "") it else getString(R.string.default_weather_app) it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
it == IntentHelper.REFRESH_WIDGET_OPTION -> "None, the widget will be refreshed"
it != IntentHelper.DEFAULT_OPTION -> it
else -> getString(R.string.default_weather_app)
}
} }
} }
} }
@ -163,19 +173,25 @@ class GesturesFragment : Fragment() {
} }
binding.actionCalendarApp.setOnClickListener { binding.actionCalendarApp.setOnClickListener {
startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java), RequestCode.CALENDAR_APP_REQUEST_CODE.code) startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java).apply {
putExtra(Constants.RESULT_APP_PACKAGE, Preferences.calendarAppPackage)
}, RequestCode.CALENDAR_APP_REQUEST_CODE.code)
} }
binding.actionClockApp.setOnClickListener { binding.actionClockApp.setOnClickListener {
startActivityForResult( startActivityForResult(
Intent(requireContext(), ChooseApplicationActivity::class.java), Intent(requireContext(), ChooseApplicationActivity::class.java).apply {
putExtra(Constants.RESULT_APP_PACKAGE, Preferences.clockAppPackage)
},
RequestCode.CLOCK_APP_REQUEST_CODE.code RequestCode.CLOCK_APP_REQUEST_CODE.code
) )
} }
binding.actionWeatherApp.setOnClickListener { binding.actionWeatherApp.setOnClickListener {
startActivityForResult( startActivityForResult(
Intent(requireContext(), ChooseApplicationActivity::class.java), Intent(requireContext(), ChooseApplicationActivity::class.java).apply {
putExtra(Constants.RESULT_APP_PACKAGE, Preferences.weatherAppPackage)
},
RequestCode.WEATHER_APP_REQUEST_CODE.code RequestCode.WEATHER_APP_REQUEST_CODE.code
) )
} }
@ -189,4 +205,37 @@ class GesturesFragment : Fragment() {
binding.scrollView.isScrollable = true binding.scrollView.isScrollable = true
} }
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK && data != null && data.hasExtra(Constants.RESULT_APP_NAME) && data.hasExtra(Constants.RESULT_APP_PACKAGE)) {
when (requestCode) {
RequestCode.CALENDAR_APP_REQUEST_CODE.code -> {
Preferences.bulk {
calendarAppName = data.getStringExtra(Constants.RESULT_APP_NAME) ?: IntentHelper.DEFAULT_OPTION
calendarAppPackage = data.getStringExtra(Constants.RESULT_APP_PACKAGE) ?: IntentHelper.DEFAULT_OPTION
}
}
RequestCode.EVENT_APP_REQUEST_CODE.code -> {
Preferences.bulk {
eventAppName = data.getStringExtra(Constants.RESULT_APP_NAME) ?: IntentHelper.DEFAULT_OPTION
eventAppPackage = data.getStringExtra(Constants.RESULT_APP_PACKAGE) ?: IntentHelper.DEFAULT_OPTION
}
}
RequestCode.WEATHER_APP_REQUEST_CODE.code -> {
Preferences.bulk {
weatherAppName = data.getStringExtra(Constants.RESULT_APP_NAME) ?: IntentHelper.DEFAULT_OPTION
weatherAppPackage = data.getStringExtra(Constants.RESULT_APP_PACKAGE) ?: IntentHelper.DEFAULT_OPTION
}
}
RequestCode.CLOCK_APP_REQUEST_CODE.code -> {
Preferences.bulk {
clockAppName = data.getStringExtra(Constants.RESULT_APP_NAME) ?: IntentHelper.DEFAULT_OPTION
clockAppPackage = data.getStringExtra(Constants.RESULT_APP_PACKAGE) ?: IntentHelper.DEFAULT_OPTION
}
}
}
MainWidget.updateWidget(requireContext())
}
super.onActivityResult(requestCode, resultCode, data)
}
} }

View File

@ -274,22 +274,23 @@ class GlanceTabFragment : Fragment() {
} }
Constants.GlanceProviderId.EVENTS -> { Constants.GlanceProviderId.EVENTS -> {
isVisible = isVisible =
Preferences.showEventsAsGlanceProvider && Preferences.showEvents && requireContext().checkGrantedPermission( Preferences.showEventsAsGlanceProvider
Manifest.permission.READ_CALENDAR val hasError = !Preferences.showEvents || !requireContext().checkGrantedPermission(
) Manifest.permission.READ_CALENDAR
)
injector.text( injector.text(
R.id.label, R.id.label,
if (isVisible) getString(R.string.settings_visible) else getString( if (isVisible && !hasError) getString(R.string.settings_visible) else getString(
R.string.settings_not_visible R.string.settings_not_visible
) )
) )
injector.visibility( injector.visibility(
R.id.error_icon, R.id.error_icon,
if (isVisible) View.GONE else View.VISIBLE if (isVisible && hasError) View.VISIBLE else View.GONE
) )
injector.visibility( injector.visibility(
R.id.info_icon, R.id.info_icon,
if (isVisible) View.VISIBLE else View.GONE if (!(isVisible && hasError)) View.VISIBLE else View.GONE
) )
} }
} }

View File

@ -6,7 +6,6 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@ -29,7 +28,6 @@ import com.tommasoberlose.anotherwidget.ui.activities.tabs.CustomFontActivity
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.activities.tabs.CustomDateActivity import com.tommasoberlose.anotherwidget.ui.activities.tabs.CustomDateActivity
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.isDarkTheme import com.tommasoberlose.anotherwidget.utils.isDarkTheme
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay

View File

@ -209,13 +209,6 @@ class WeatherFragment : Fragment() {
WeatherReceiver.setUpdates(requireContext()) WeatherReceiver.setUpdates(requireContext())
checkLocationPermission() checkLocationPermission()
} }
RequestCode.WEATHER_APP_REQUEST_CODE.code -> {
Preferences.bulk {
weatherAppName = data?.getStringExtra(Constants.RESULT_APP_NAME) ?: getString(R.string.default_weather_app)
weatherAppPackage = data?.getStringExtra(Constants.RESULT_APP_PACKAGE) ?: ""
}
MainWidget.updateWidget(requireContext())
}
RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> { RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
checkLocationPermission() checkLocationPermission()
} }

View File

@ -96,7 +96,6 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
val showWallpaper = Preferences.asLiveData(Preferences::showWallpaper) val showWallpaper = Preferences.asLiveData(Preferences::showWallpaper)
val showPreview = Preferences.asLiveData(Preferences::showPreview) val showPreview = Preferences.asLiveData(Preferences::showPreview)
val installedIntegrations = Preferences.asLiveData(Preferences::installedIntegrations) val installedIntegrations = Preferences.asLiveData(Preferences::installedIntegrations)
var colorClipboard: ArrayList<String> = ArrayList()
// UI // UI
val fragmentScrollY = MutableLiveData<Int>() val fragmentScrollY = MutableLiveData<Int>()
@ -169,19 +168,4 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
addSource(Preferences.asLiveData(Preferences::installedIntegrations)) { value = true } addSource(Preferences.asLiveData(Preferences::installedIntegrations)) { value = true }
} }
init {
with(context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager) {
if (hasPrimaryClip()) {
(0..primaryClip!!.itemCount).forEach {
try {
val color = primaryClip!!.getItemAt(it).text.toString()
if (color.isColor()) {
colorClipboard.add(color)
}
} catch (ex: Exception) {}
}
}
}
}
} }

View File

@ -0,0 +1,11 @@
package com.tommasoberlose.anotherwidget.ui.viewmodels.tabs
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
class MediaInfoFormatViewModel(application: Application) : AndroidViewModel(application) {
val mediaInfoFormatInput: MutableLiveData<String> = MutableLiveData(if (Preferences.mediaInfoFormat == "") MediaPlayerHelper.DEFAULT_MEDIA_INFO_FORMAT else Preferences.mediaInfoFormat)
}

View File

@ -17,6 +17,7 @@ import android.util.Log
import android.util.TypedValue import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.RemoteViews import android.widget.RemoteViews
import android.widget.TextView import android.widget.TextView
@ -34,6 +35,7 @@ import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
import com.tommasoberlose.anotherwidget.helpers.ImageHelper.applyShadow import com.tommasoberlose.anotherwidget.helpers.ImageHelper.applyShadow
import com.tommasoberlose.anotherwidget.receivers.* import com.tommasoberlose.anotherwidget.receivers.*
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.convertDpToPixel
import com.tommasoberlose.anotherwidget.utils.isDarkTheme import com.tommasoberlose.anotherwidget.utils.isDarkTheme
import com.tommasoberlose.anotherwidget.utils.toPixel import com.tommasoberlose.anotherwidget.utils.toPixel
import java.text.DateFormat import java.text.DateFormat
@ -1072,7 +1074,10 @@ class MainWidget : AppWidgetProvider() {
// Dividers // Dividers
arrayOf(bindingView.divider1, bindingView.divider2, bindingView.divider3).forEach { arrayOf(bindingView.divider1, bindingView.divider2, bindingView.divider3).forEach {
it.isVisible = Preferences.showDividers it.visibility = if (Preferences.showDividers) View.VISIBLE else View.INVISIBLE
it.layoutParams = (it.layoutParams as ViewGroup.MarginLayoutParams).apply {
this.marginEnd = if (Preferences.showDividers) 8f.convertDpToPixel(context).toInt() else 0
}
} }
eventRepository.close() eventRepository.close()

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M15,1L4,1c-1.1,0 -2,0.9 -2,2v13c0,0.55 0.45,1 1,1s1,-0.45 1,-1L4,4c0,-0.55 0.45,-1 1,-1h10c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM18,21L9,21c-0.55,0 -1,-0.45 -1,-1L8,8c0,-0.55 0.45,-1 1,-1h9c0.55,0 1,0.45 1,1v12c0,0.55 -0.45,1 -1,1z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M19,2h-4.18C14.4,0.84 13.3,0 12,0S9.6,0.84 9.18,2L5,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,4c0,-1.1 -0.9,-2 -2,-2zM12,2c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM18,20L6,20c-0.55,0 -1,-0.45 -1,-1L5,5c0,-0.55 0.45,-1 1,-1h1v1c0,1.1 0.9,2 2,2h6c1.1,0 2,-0.9 2,-2L17,4h1c0.55,0 1,0.45 1,1v14c0,0.55 -0.45,1 -1,1z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M8.83,6l-3.7,-3.7C5.42,1.55 6.15,1 7,1l10,0.01c1.1,0 2,0.89 2,1.99v13.17l-2,-2V6H8.83zM20.49,21.9c-0.39,0.39 -1.02,0.39 -1.41,0l-0.2,-0.2C18.58,22.45 17.85,23 17,23H7c-1.1,0 -2,-0.9 -2,-2V7.83l-2.9,-2.9c-0.39,-0.39 -0.39,-1.02 0,-1.41c0.39,-0.39 1.02,-0.39 1.41,0l16.97,16.97C20.88,20.88 20.88,21.51 20.49,21.9zM15.17,18L7,9.83V18H15.17z"/>
</vector>

View File

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com.tommasoberlose.anotherwidget.ui.viewmodels.tabs.MediaInfoFormatViewModel" />
</data>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/colorPrimaryDark">
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="2dp"
app:cardCornerRadius="0dp"
android:id="@+id/toolbar"
app:cardBackgroundColor="@color/colorPrimary">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="56dp"
android:gravity="center_vertical"
android:paddingLeft="8dp"
android:paddingRight="8dp">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackgroundBorderless"
android:id="@+id/action_back"
app:tint="@color/colorPrimaryText"
android:src="@drawable/round_arrow_back_24" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/settings_show_music_title"
android:paddingStart="8dp"
android:layout_marginEnd="48dp"
android:gravity="center"
style="@style/AnotherWidget.Main.Title"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="2dp"
app:cardCornerRadius="0dp"
app:cardBackgroundColor="@color/colorPrimary">
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/colorPrimaryDark"
app:cardCornerRadius="9dp"
app:cardElevation="0dp"
android:layout_marginTop="8dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="48dp"
android:background="@color/colorPrimaryDark"
android:paddingStart="16dp"
android:paddingEnd="56dp"
android:id="@+id/media_info_format_input"
android:gravity="center_vertical|start"
android:textDirection="locale"
android:textAlignment="viewStart"
android:lines="1"
android:maxLines="1"
android:singleLine="true"
android:hint="@string/song_info_format_activity_title"
android:fontFamily="@font/google_sans"
android:text="@={viewModel.mediaInfoFormatInput}"
android:autofillHints=""
tools:ignore="TextFields" />
</RelativeLayout>
</com.google.android.material.card.MaterialCardView>
</com.google.android.material.card.MaterialCardView>
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardElevation="2dp"
app:cardCornerRadius="0dp"
app:cardBackgroundColor="@color/colorPrimary">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginTop="8dp"
android:layout_marginBottom="16dp">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="48dp"
android:id="@+id/media_info_format_input_value"
android:textAppearance="@style/AnotherWidget.Settings.Title"
android:letterSpacing="0"
android:textColor="@color/colorPrimaryText"
android:textSize="18sp"
app:textAllCaps="false"
android:gravity="center_vertical|start"
android:textAlignment="viewStart"
android:maxLines="1"
android:lines="1"
android:singleLine="true"
android:ellipsize="end"
android:layout_marginLeft="32dp"
android:layout_marginRight="32dp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<androidx.core.widget.ContentLoadingProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true"
android:indeterminateTint="@color/colorAccent"
android:layout_marginTop="-7dp"
android:id="@+id/loader"
style="@style/Widget.AppCompat.ProgressBar.Horizontal" />
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="64dp"
android:paddingTop="16dp"
android:clipToPadding="false"
android:id="@+id/list_view" />
</RelativeLayout>
</LinearLayout>
</layout>

View File

@ -21,8 +21,8 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingBottom="8dp" android:paddingBottom="4dp"
android:paddingTop="8dp" android:paddingTop="4dp"
android:orientation="horizontal" android:orientation="horizontal"
android:gravity="center_vertical|start"> android:gravity="center_vertical|start">
<ImageView <ImageView

View File

@ -38,7 +38,7 @@
android:id="@+id/message" android:id="@+id/message"
android:gravity="start" android:gravity="start"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:text="Messaggio molto lungo di cui voirre akjcbasaskdask flasdas fashbdfjah fahsbd ajsbd " android:text=""
android:textColor="@color/colorPrimaryText"/> android:textColor="@color/colorPrimaryText"/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout

View File

@ -24,6 +24,7 @@
android:paddingRight="32dp" android:paddingRight="32dp"
android:id="@+id/header_text" android:id="@+id/header_text"
android:text="" android:text=""
android:textSize="20sp"
android:textColor="@color/colorPrimaryText"/> android:textColor="@color/colorPrimaryText"/>
<androidx.appcompat.widget.AppCompatTextView <androidx.appcompat.widget.AppCompatTextView
android:textAppearance="@style/AnotherWidget.Settings.Subtitle" android:textAppearance="@style/AnotherWidget.Settings.Subtitle"

View File

@ -16,23 +16,32 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/header" android:id="@+id/header"
android:visibility="gone"
android:orientation="vertical"> android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView <LinearLayout
android:textAppearance="@style/AnotherWidget.Settings.Title"
app:textAllCaps="false"
android:letterSpacing="0"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:paddingTop="16dp" android:orientation="horizontal"
android:paddingBottom="8dp" android:paddingLeft="16dp"
android:paddingLeft="32dp" android:paddingRight="16dp"
android:paddingRight="32dp" android:gravity="center_vertical">
android:gravity="start" <androidx.appcompat.widget.AppCompatTextView
android:textAlignment="viewStart" android:textAppearance="@style/AnotherWidget.Settings.Title"
android:id="@+id/header_text" app:textAllCaps="false"
android:text="" android:letterSpacing="0"
android:textColor="@color/colorPrimaryText"/> android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="8dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:gravity="start"
android:textSize="20sp"
android:textAlignment="viewStart"
android:id="@+id/header_text"
android:text="@string/settings_font_color_title"
android:textColor="@color/colorPrimaryText"/>
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1dp" android:layout_height="1dp"

View File

@ -31,7 +31,6 @@
android:src="@drawable/round_arrow_back_24" android:src="@drawable/round_arrow_back_24"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:transitionName="action_back"
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
app:tint="@color/colorPrimaryText" app:tint="@color/colorPrimaryText"
android:layout_centerVertical="true" android:layout_centerVertical="true"
@ -65,6 +64,7 @@
android:background="?attr/selectableItemBackgroundBorderless" android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:transitionName="action_back"
android:padding="8dp" android:padding="8dp"
android:scaleX="-1" android:scaleX="-1"
android:src="@drawable/round_short_text_24" android:src="@drawable/round_short_text_24"

View File

@ -177,6 +177,39 @@
style="@style/AnotherWidget.Settings.Subtitle"/> style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:paddingLeft="24dp"
android:paddingRight="24dp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/action_change_media_info_format"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
style="@style/AnotherWidget.Settings.Title"
android:text="@string/song_info_format_activity_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:text="@string/song_info_format_activity_subtitle"
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="add_widget">Hinzufügen</string> <string name="add_widget">Widget hinzufügen</string>
<!-- Display --> <!-- Display -->
<string name="settings_general_title">Anzeige</string> <string name="settings_general_title">Anzeige</string>
@ -16,7 +16,7 @@
<string name="settings_custom_font_title">Widget Schriftart</string> <string name="settings_custom_font_title">Widget Schriftart</string>
<string name="custom_font_subtitle_0">System Schriftart</string> <string name="custom_font_subtitle_0">System Schriftart</string>
<string name="custom_font_subtitle_1">Google Sans</string> <string name="custom_font_subtitle_1">Google Sans</string>
<string name="custom_date_format">Eigenes Format</string> <string name="custom_date_format">Eigenes Datumsformat</string>
<string name="alpha">Alpha</string> <string name="alpha">Alpha</string>
<string name="transparent">Transparent</string> <string name="transparent">Transparent</string>
<string name="settings_show_dividers_title">Texttrennlinien anzeigen</string> <string name="settings_show_dividers_title">Texttrennlinien anzeigen</string>
@ -26,8 +26,8 @@
<string name="action_capitalize_the_date">Datum groß schreiben</string> <string name="action_capitalize_the_date">Datum groß schreiben</string>
<string name="settings_date_format_title">Datumsformat</string> <string name="settings_date_format_title">Datumsformat</string>
<string name="header_widget_background">Widget Hintergrund</string> <string name="header_widget_background">Widget Hintergrund</string>
<string name="settings_secondary_row_top_margin_title">Abstand</string> <string name="settings_secondary_row_top_margin_title">Zeilenabstand</string>
<string name="action_custom_font_to_search">Benutzerdefinierte Schriftart...</string> <string name="action_custom_font_to_search">Benutzerdefinierte Schriftart</string>
<!-- Calendar --> <!-- Calendar -->
<string name="settings_calendar_title">Kalender</string> <string name="settings_calendar_title">Kalender</string>
@ -51,7 +51,7 @@
<string name="settings_show_until_subtitle_5">7 Tage vorher</string> <string name="settings_show_until_subtitle_5">7 Tage vorher</string>
<string name="settings_show_until_title">Zeige Termine mindestens</string> <string name="settings_show_until_title">Zeige Termine mindestens</string>
<string name="day_char">T.</string> <string name="day_char">T.</string>
<string name="settings_calendar_app_title">Standard Kalender App</string> <string name="settings_calendar_app_title">Kalender</string>
<string name="error_no_calendar">Keine Kalender gefunden.</string> <string name="error_no_calendar">Keine Kalender gefunden.</string>
<string name="tomorrow">morgen</string> <string name="tomorrow">morgen</string>
<string name="today">heute</string> <string name="today">heute</string>
@ -76,7 +76,7 @@
<string name="settings_attendee_status_title">Teilnahmestatus</string> <string name="settings_attendee_status_title">Teilnahmestatus</string>
<string name="settings_attendee_status_subtitle">Akzeptierte oder abgelehnte Termine filtern</string> <string name="settings_attendee_status_subtitle">Akzeptierte oder abgelehnte Termine filtern</string>
<string name="settings_busy_events_title">Relevante Termine</string> <string name="settings_busy_events_title">Relevante Termine</string>
<string name="settings_busy_events_subtitle">Nur Termine anzeigen, bei \ndenen Sie beschäftigt sind</string> <string name="settings_busy_events_subtitle">Nur Termine anzeigen, bei denen Sie beschäftigt sind</string>
<string name="attendee_status_accepted">Akzeptierte Termine</string> <string name="attendee_status_accepted">Akzeptierte Termine</string>
<string name="attendee_status_invited">Einladungen zu Terminen</string> <string name="attendee_status_invited">Einladungen zu Terminen</string>
<string name="attendee_status_declined">Abgelehnte Termine</string> <string name="attendee_status_declined">Abgelehnte Termine</string>
@ -94,27 +94,19 @@
<string name="settings_weather_refresh_period_subtitle_4">12 Stunden</string> <string name="settings_weather_refresh_period_subtitle_4">12 Stunden</string>
<string name="settings_weather_refresh_period_subtitle_5">24 Stunden</string> <string name="settings_weather_refresh_period_subtitle_5">24 Stunden</string>
<string name="settings_custom_location_title">Standort</string> <string name="settings_custom_location_title">Standort</string>
<string name="custom_location_gps">GPS-Standort verwenden</string> <string name="custom_location_gps">GPS-Standort</string>
<string name="show_weather_visible">Wetterinfos sind sichtbar</string> <string name="show_weather_visible">Wetterinfos sind sichtbar</string>
<string name="show_weather_not_visible">Wetterinfos sind ausgeblendet</string> <string name="show_weather_not_visible">Wetterinfos sind ausgeblendet</string>
<string name="settings_weather_app_title">Klick auf das Wetter öffnet</string> <string name="settings_weather_app_title">Wetter</string>
<string name="settings_weather_provider_api_key_title">Wetter API Key</string> <string name="settings_weather_provider_api_key_title">Wetter API Key</string>
<string name="settings_weather_provider_api_key_subtitle_all_set">Der Wetteranbieter ist korrekt konfiguriert</string> <string name="settings_weather_provider_api_key_subtitle_all_set">Der Wetteranbieter ist korrekt konfiguriert.</string>
<string name="settings_weather_provider_api_key_subtitle_not_set">Der Wetteranbieter muss konfiguriert werden</string> <string name="settings_weather_provider_api_key_subtitle_not_set">Der Wetteranbieter muss konfiguriert werden.</string>
<string name="api_key_hint">OpenWeather API Schlüssel</string> <string name="api_key_hint">OpenWeather API Schlüssel</string>
<string name="default_weather_app">Google Weather</string> <string name="default_weather_app">Google Weather</string>
<string name="weather_warning">Google Awareness Wetter ist veraltet. Es wird nun ein API-Schlüssel von einem Drittanbieter benötigt, um das Wetter im Widget anzuzeigen.</string> <string name="weather_warning">Google Awareness Wetter ist veraltet. Es wird nun ein API-Schlüssel von einem Drittanbieter benötigt, um das Wetter im Widget anzuzeigen.</string>
<string name="api_key_title_1">OpenWeatherMap Konto registrieren</string>
<string name="api_key_subtitle_1">Registriere ein kostenloses Konto bei OpenWeatherMap. Es sollte nur ein paar Minuten dauern.</string>
<string name="api_key_title_2">API-Schlüssel kopieren</string>
<string name="api_key_subtitle_2">Gehe in die Kontoeinstellungen und kopiere den Standardschlüssel im API-Schlüsselmenü.</string>
<string name="api_key_title_3">Schlüssel in die App eingeben</string>
<string name="api_key_subtitle_3">Füge den Schlüssel in das obere Feld ein und speicher ihn. Sobald der Schlüssel aktiviert ist, wird das Wetter angezeigt.</string>
<string name="action_open_provider">Öffne OpenWeatherMap.org</string>
<string name="api_key_info_all_set">Es kann bis zu zehn Minuten dauern, bis der API-Schlüssel aktiviert ist. Das Wetter wird aktualisiert, sobald es verfügbar ist.</string>
<string name="settings_weather_icon_pack_title">Icon Pack</string> <string name="settings_weather_icon_pack_title">Icon Pack</string>
<string name="settings_weather_icon_pack_default">Icon Pack %d</string> <string name="settings_weather_icon_pack_default">Icon Pack %d</string>
<string name="background_location_warning">Wenn GPS aktiviert ist, sammeln wir Standortdaten, um die Wetterinformationen zu aktualisieren, auch wenn die App geschlossen oder nicht in Gebrauch ist.\nDie Daten werden nicht für andere Zwecke verwendet.</string> <string name="background_location_warning">Wenn GPS-Standort ausgewählt ist, sammeln wir Standortdaten, um die Wetterinformationen zu aktualisieren, auch wenn die App geschlossen oder nicht in Gebrauch ist.\nDie Daten werden nicht für andere Zwecke verwendet.</string>
<string name="settings_weather_provider_api">Wetterdienst</string> <string name="settings_weather_provider_api">Wetterdienst</string>
<string name="weather_provider_info_open_weather_title">Dieser Wetteranbieter benötigt einen\nAPI-Schlüssel, um korrekt zu funktionieren.</string> <string name="weather_provider_info_open_weather_title">Dieser Wetteranbieter benötigt einen\nAPI-Schlüssel, um korrekt zu funktionieren.</string>
@ -147,9 +139,14 @@
<string name="weather_select_a_provider">Wählen einen Anbieter</string> <string name="weather_select_a_provider">Wählen einen Anbieter</string>
<string name="weather_provider_activity_subtitle">Wählen Sie einen Wetterdienst aus der Liste aus.\nEinige Anbieter benötigen ein kostenloses\nBenutzerkonto, allerdings sind sie\ndafür in der Regel genauer.</string> <string name="weather_provider_activity_subtitle">Wählen Sie einen Wetterdienst aus der Liste aus.\nEinige Anbieter benötigen ein kostenloses\nBenutzerkonto, allerdings sind sie\ndafür in der Regel genauer.</string>
<string name="location_access_notification_channel_name">Hintergrunddienst</string>
<string name="location_access_notification_channel_description">Dienst zur Aktualisierung des Wetters anhand des aktuellen Standorts des Benutzers.</string>
<string name="location_access_notification_title">Wetter wird aktualisiert…</string>
<string name="location_access_notification_subtitle">Das Wetter wird basierend auf Ihrem aktuellen Standort aktualisiert.</string>
<!-- Clock --> <!-- Clock -->
<string name="settings_clock_title">Uhr</string> <string name="settings_clock_title">Uhr</string>
<string name="settings_clock_app_title">Klick auf die Uhr öffnet</string> <string name="settings_clock_app_title">Uhr</string>
<string name="title_show_clock">Uhr anzeigen</string> <string name="title_show_clock">Uhr anzeigen</string>
<string name="show_clock_visible">Uhr ist sichtbar</string> <string name="show_clock_visible">Uhr ist sichtbar</string>
<string name="show_clock_not_visible">Uhr ist nicht sichtbar</string> <string name="show_clock_not_visible">Uhr ist nicht sichtbar</string>
@ -167,7 +164,7 @@
<!-- Glance --> <!-- Glance -->
<string name="settings_show_next_alarm_title">Nächster Wecker</string> <string name="settings_show_next_alarm_title">Nächster Wecker</string>
<string name="settings_at_a_glance_title">Überblick</string> <string name="settings_at_a_glance_title">Auf einen Blick</string>
<string name="settings_show_music_title">Aktuell spielendes Lied</string> <string name="settings_show_music_title">Aktuell spielendes Lied</string>
<string name="settings_request_notification_access">Wir benötigen Zugriff auf die Benachrichtigungen, um auf das aktuell abgespielte Lied zugreifen zu können.</string> <string name="settings_request_notification_access">Wir benötigen Zugriff auf die Benachrichtigungen, um auf das aktuell abgespielte Lied zugreifen zu können.</string>
<string name="settings_request_last_notification_access">Wir benötigen Zugriff auf die Benachrichtigungen, um Ihre letzten Benachrichtigungen sehen zu können.</string> <string name="settings_request_last_notification_access">Wir benötigen Zugriff auf die Benachrichtigungen, um Ihre letzten Benachrichtigungen sehen zu können.</string>
@ -176,22 +173,22 @@
<string name="description_show_glance_visible">Dienst ist aktiviert</string> <string name="description_show_glance_visible">Dienst ist aktiviert</string>
<string name="description_show_glance_not_visible">Dienst ist deaktiviert</string> <string name="description_show_glance_not_visible">Dienst ist deaktiviert</string>
<string name="settings_sort_glance_providers_title">Priorität der Datenquelle</string> <string name="settings_sort_glance_providers_title">Priorität der Datenquelle</string>
<string name="settings_sort_glance_providers_subtitle">Priorität der jeweiligen Dienste ändern</string> <string name="settings_sort_glance_providers_subtitle">Priorität der jeweiligen Dienste ändern, indem Sie die Liste per Drag-and-Drop sortieren.</string>
<string name="settings_custom_notes_title">Benutzerdefinierte Notiz</string> <string name="settings_custom_notes_title">Benutzerdefinierte Notiz</string>
<string name="settings_low_battery_level_title">Akku</string>
<string name="settings_daily_steps_title">Tägliche Schritte</string> <string name="settings_daily_steps_title">Tägliche Schritte</string>
<string name="battery_low_warning">Niedriger Akkustand</string>
<string name="daily_steps_counter">%d Schritte bis jetzt</string> <string name="daily_steps_counter">%d Schritte bis jetzt</string>
<string name="settings_low_battery_level_title">Akku</string>
<string name="battery_low_warning">Niedriger Akkustand</string>
<string name="charging">Wird aufgeladen</string> <string name="charging">Wird aufgeladen</string>
<string name="charged">Aufgeladen</string> <string name="charged">Aufgeladen</string>
<string name="providers">Dienste</string> <string name="providers">Dienste</string>
<string name="glance_info">Überblick Informationen sind nur dann sichtbar, wenn keine Termine angezeigt werden und wenn einige Bedingungen erfüllt sind.</string> <string name="glance_info">Informationen auf einen Blick sind nur dann sichtbar, wenn gerade keine Termine angezeigt werden und einige Bedingungen erfüllt sind.</string>
<string name="settings_music_players_filter_title">Musik Player</string> <string name="settings_music_players_filter_title">Musik Player</string>
<string name="settings_music_players_filter_subtitle">Wähle die gewünschten Musik Player aus</string> <string name="settings_music_players_filter_subtitle">Wähle die gewünschten Musik Player aus</string>
<string name="settings_show_music_subtitle">Wir verwenden die Benachrichtigung der Musik-Player, um das aktuell gespielte Lied anzuzeigen.</string> <string name="settings_show_music_subtitle">Wir verwenden die Benachrichtigung der Musik-Player, um das aktuell gespielte Lied anzuzeigen.</string>
<string name="settings_low_battery_level_subtitle">Darüber informieren, wenn der Akku schwach ist oder aufgeladen wird.</string> <string name="settings_low_battery_level_subtitle">Darüber informiert werden, wenn der Akku schwach ist oder aufgeladen wird.</string>
<string name="settings_daily_steps_subtitle">Zeigt die täglichen Schritte, nachdem Sie einen Spaziergang oder einen Lauf beendet haben.</string> <string name="settings_daily_steps_subtitle">Zeigt die täglichen Schritte, nachdem Sie einen Spaziergang oder einen Lauf beendet haben.</string>
<string name="settings_show_next_alarm_subtitle">Zeigt den nächsten Alarm an. Stellen Sie sicher, dass Ihre standardmäßige Uhren-App die einzige ist, die Alarme auf dem Gerät einstellt.</string> <string name="settings_show_next_alarm_subtitle">Zeigt den nächsten Alarm an.\nStellen Sie sicher, dass Ihre standardmäßige Uhren-App die einzige ist, die Alarme auf dem Gerät einstellt.</string>
<string name="settings_show_next_alarm_app_title">Alarm gesetzt durch %s</string> <string name="settings_show_next_alarm_app_title">Alarm gesetzt durch %s</string>
<string name="settings_show_next_alarm_app_subtitle_wrong">Der nächste Wecker scheint falsch zu sein</string> <string name="settings_show_next_alarm_app_subtitle_wrong">Der nächste Wecker scheint falsch zu sein</string>
<string name="settings_show_next_alarm_app_subtitle_correct">Der nächste Wecker scheint korrekt zu sein</string> <string name="settings_show_next_alarm_app_subtitle_correct">Der nächste Wecker scheint korrekt zu sein</string>
@ -236,6 +233,10 @@
<item>15 Minuten</item> <item>15 Minuten</item>
<item>dem Entfernen</item> <item>dem Entfernen</item>
</string-array> </string-array>
<string name="settings_show_events_as_glance_provider_title">Termine</string>
<string name="settings_show_events_as_glance_provider_subtitle">Zeigt eine Vorschau Ihrer Termine und lässt das aktuelle Datum angezeigt.</string>
<string name="settings_show_events_as_glance_provider_error">Bitte aktiviere die Anzeige der Termine im Kalender Menü und erteile die erforderlichen Berechtigungen</string>
<string name="events_glance_provider_format">%1$s %2$s</string>
<!-- Settings --> <!-- Settings -->
<string name="action_share">Teilen</string> <string name="action_share">Teilen</string>
@ -267,7 +268,7 @@
<string name="settings_app_version_title">App Version</string> <string name="settings_app_version_title">App Version</string>
<string name="settings_title_show_wallpaper">Hintergrundbild anzeigen</string> <string name="settings_title_show_wallpaper">Hintergrundbild anzeigen</string>
<string name="support_refresh_widget_subtitle">Neustart des Widget Dienstes erzwingen</string> <string name="support_refresh_widget_subtitle">Neustart des Widget Dienstes erzwingen</string>
<string name="settings_feedback_subtitle">Dies ist ein Open-Source-Projekt, du kannst gerne helfen.</string> <string name="settings_feedback_subtitle">Sie können gerne unserem Projekt helfen!</string>
<string name="settings_feedback_title">Feedback und Vorschläge</string> <string name="settings_feedback_title">Feedback und Vorschläge</string>
<string name="xiaomi_warning_title">Xiaomi Geräte</string> <string name="xiaomi_warning_title">Xiaomi Geräte</string>
<string name="xiaomi_warning_message">Aktiviere die Berechtigung zum Anzeigen von Popup-Fenstern, wenn die App im Hintergrund ausgeführt wird, unter \"Andere Berechtigungen\" in den App-Einstellungen. Andernfalls kann beim Klicken auf das Widget keine Anwendung geöffnet werden.</string> <string name="xiaomi_warning_message">Aktiviere die Berechtigung zum Anzeigen von Popup-Fenstern, wenn die App im Hintergrund ausgeführt wird, unter \"Andere Berechtigungen\" in den App-Einstellungen. Andernfalls kann beim Klicken auf das Widget keine Anwendung geöffnet werden.</string>
@ -276,10 +277,10 @@
<string name="settings_title">Einstellungen</string> <string name="settings_title">Einstellungen</string>
<string name="style_header">Stil</string> <string name="style_header">Stil</string>
<string name="actions_header">Aktionen</string> <string name="actions_header">Aktionen</string>
<string name="provider_header">Konfiguration</string> <string name="provider_header">Provider</string>
<string name="appearance_header">Erscheinungsbild</string> <string name="appearance_header">Erscheinungsbild</string>
<string name="preferences_header">Präferenzen</string> <string name="preferences_header">Präferenzen</string>
<string name="settings_privacy_policy_title"><![CDATA[AGB & Datenschutz]]></string> <string name="settings_privacy_policy_title"><![CDATA[Rechtliches & Datenschutz]]></string>
<string name="settings_privacy_policy_subtitle">Datenschutzrichtlinien der App anzeigen</string> <string name="settings_privacy_policy_subtitle">Datenschutzrichtlinien der App anzeigen</string>
<string name="project_header">Open-Source Projekt</string> <string name="project_header">Open-Source Projekt</string>
<string name="information_header">Information</string> <string name="information_header">Information</string>
@ -300,4 +301,17 @@
<string name="nothing">Nichts</string> <string name="nothing">Nichts</string>
<string name="action_dismiss">Verwerfen</string> <string name="action_dismiss">Verwerfen</string>
<string name="action_accept">Akzeptieren</string> <string name="action_accept">Akzeptieren</string>
<!-- More -->
<string name="look_and_feel_header"><![CDATA[Erscheinungsbild]]></string>
<string name="typography_settings_title">Typografie</string>
<string name="typography_settings_subtitle">Schriftart, Größe und Farbe des Textes einstellen</string>
<string name="layout_settings_title">Layout</string>
<string name="gestures_settings_subtitle">Aktionen, Verhalten und Verknüpfungen</string>
<string name="gestures_settings_title">Gesten</string>
<string name="gestures_amp_input_header"><![CDATA[Gesten & Bedienung]]></string>
<string name="clock_settings_subtitle">Größe, Farbe und Zeitzonen einstellen</string>
<string name="layout_settings_subtitle">Widget Abstände und Anpassungen</string>
<string name="smart_content_header">Smarte Inhalte</string>
<string name="font_family_settings_title">Schriftfamilie</string>
</resources> </resources>

View File

@ -80,6 +80,11 @@
<string name="attendee_status_accepted">Événements acceptés</string> <string name="attendee_status_accepted">Événements acceptés</string>
<string name="attendee_status_invited">Invitations à des évmts</string> <string name="attendee_status_invited">Invitations à des évmts</string>
<string name="attendee_status_declined">Événements refusés</string> <string name="attendee_status_declined">Événements refusés</string>
<string name="calendar_sync_notification_channel_id" translatable="false">calendar-sync</string>
<string name="calendar_sync_notification_channel_name">Service de synchronisation du calendrier</string>
<string name="calendar_sync_notification_channel_description">Service utilisé pour synchroniser les événements du calendrier.</string>
<string name="calendar_sync_notification_title">Synchronisation du calendrier...</string>
<!-- Weather --> <!-- Weather -->
<string name="settings_weather_title">Météo</string> <string name="settings_weather_title">Météo</string>
@ -140,7 +145,7 @@
<string name="weather_provider_activity_subtitle">Sélectionnez un fournisseur météo dans la liste.\nCertains fournisseurs ont besoin d\'un\ncompte personnel gratuit pour fonctionner,\nmais ils sont généralement plus précis.</string> <string name="weather_provider_activity_subtitle">Sélectionnez un fournisseur météo dans la liste.\nCertains fournisseurs ont besoin d\'un\ncompte personnel gratuit pour fonctionner,\nmais ils sont généralement plus précis.</string>
<string name="location_access_notification_channel_id" translatable="false">location-access</string> <string name="location_access_notification_channel_id" translatable="false">location-access</string>
<string name="location_access_notification_channel_name">Arrière-plan</string> <string name="location_access_notification_channel_name">Service en arrière-plan</string>
<string name="location_access_notification_channel_description">Service utilisé pour actualiser la météo en fonction de l\'emplacement actuel de l\'utilisateur.</string> <string name="location_access_notification_channel_description">Service utilisé pour actualiser la météo en fonction de l\'emplacement actuel de l\'utilisateur.</string>
<string name="location_access_notification_title">Actualisation de la météo...</string> <string name="location_access_notification_title">Actualisation de la météo...</string>
<string name="location_access_notification_subtitle">Nous actualisons la météo en fonction de votre emplacement actuel.</string> <string name="location_access_notification_subtitle">Nous actualisons la météo en fonction de votre emplacement actuel.</string>
@ -158,7 +163,7 @@
<string name="settings_clock_bottom_margin_subtitle_small">Petite</string> <string name="settings_clock_bottom_margin_subtitle_small">Petite</string>
<string name="settings_clock_bottom_margin_subtitle_medium">Moyenne</string> <string name="settings_clock_bottom_margin_subtitle_medium">Moyenne</string>
<string name="settings_clock_bottom_margin_subtitle_large">Grande</string> <string name="settings_clock_bottom_margin_subtitle_large">Grande</string>
<string name="clock_warning">En raison de limitations technologiques, l\'horloge n\'aura pas la police personnalisée et les ombres de texte sélectionnées dans l\'onglet <b>Affichage</b>.</string> <string name="clock_warning">En raison de limitations technologiques, l\'horloge n\'aura pas la police personnalisée et les ombres de texte sélectionnées dans le menu <b>Typographie</b>.</string>
<string name="settings_clock_text_color_title">Couleur du texte</string> <string name="settings_clock_text_color_title">Couleur du texte</string>
<string name="settings_ampm_indicator_title">Afficher l\'indicateur AM/PM</string> <string name="settings_ampm_indicator_title">Afficher l\'indicateur AM/PM</string>
<string name="clock_text_header">Style du texte</string> <string name="clock_text_header">Style du texte</string>
@ -239,7 +244,7 @@
<string name="settings_show_events_as_glance_provider_title">Événements</string> <string name="settings_show_events_as_glance_provider_title">Événements</string>
<string name="settings_show_events_as_glance_provider_subtitle">Affiche un petit aperçu des événements de votre calendrier, tout en affichant toujours la date actuelle.</string> <string name="settings_show_events_as_glance_provider_subtitle">Affiche un petit aperçu des événements de votre calendrier, tout en affichant toujours la date actuelle.</string>
<string name="settings_show_events_as_glance_provider_error">Veuillez activer l\'affichage des événements dans l\'onglet <b>Calendrier</b> et accorder l\'autorisation requise.</string> <string name="settings_show_events_as_glance_provider_error">Veuillez activer l\'affichage des événements dans le menu <b>Calendrier</b> et accorder l\'autorisation requise.</string>
<string name="events_glance_provider_format">%1$s %2$s</string> <string name="events_glance_provider_format">%1$s %2$s</string>
<!-- Settings --> <!-- Settings -->
@ -305,4 +310,18 @@
<string name="nothing">Rien</string> <string name="nothing">Rien</string>
<string name="action_dismiss">REFUSER</string> <string name="action_dismiss">REFUSER</string>
<string name="action_accept">ACCEPTER</string> <string name="action_accept">ACCEPTER</string>
<!-- More -->
<string name="look_and_feel_header"><![CDATA[Apparence du widget]]></string>
<string name="typography_settings_title">Typographie</string>
<string name="typography_settings_subtitle">Définir la police, la taille et la couleur du texte</string>
<string name="layout_settings_title">Mise en page</string>
<string name="gestures_settings_subtitle">Actions, comportements et raccourcis</string>
<string name="gestures_settings_title">Gestes</string>
<string name="gestures_amp_input_header"><![CDATA[Gestes et saisie]]></string>
<string name="clock_settings_subtitle">Définir la taille, la couleur et le fuseau horaire</string>
<string name="layout_settings_subtitle">Espacement et ajustements du widget</string>
<string name="smart_content_header">Contenu intelligent</string>
<string name="font_family_settings_title">Famille de polices</string>
</resources> </resources>

View File

@ -30,6 +30,7 @@
<string name="header_widget_background">Widget background</string> <string name="header_widget_background">Widget background</string>
<string name="settings_secondary_row_top_margin_title">Rows spacing</string> <string name="settings_secondary_row_top_margin_title">Rows spacing</string>
<string name="action_custom_font_to_search">Custom font…</string> <string name="action_custom_font_to_search">Custom font…</string>
<string name="font_family_settings_title">Font family</string>
<string name="font_100" translatable="false">Thin</string> <string name="font_100" translatable="false">Thin</string>
<string name="font_200" translatable="false">Light</string> <string name="font_200" translatable="false">Light</string>
@ -40,6 +41,16 @@
<string name="font_700" translatable="false">Bold</string> <string name="font_700" translatable="false">Bold</string>
<string name="font_800" translatable="false">Black</string> <string name="font_800" translatable="false">Black</string>
<string name="font_900" translatable="false">Heavy</string> <string name="font_900" translatable="false">Heavy</string>
<string name="font_italic" translatable="false">Italic</string>
<string name="font_100_italic" translatable="false">Thin Italic</string>
<string name="font_200_italic" translatable="false">Light Italic</string>
<string name="font_300_italic" translatable="false">Book Italic</string>
<string name="font_400_italic" translatable="false">Regular Italic</string>
<string name="font_500_italic" translatable="false">Medium Italic</string>
<string name="font_600_italic" translatable="false">Semi-bold Italic</string>
<string name="font_700_italic" translatable="false">Bold Italic</string>
<string name="font_800_italic" translatable="false">Black Italic</string>
<string name="font_900_italic" translatable="false">Heavy Italic</string>
<!-- Calendar --> <!-- Calendar -->
<string name="settings_calendar_title">Calendar</string> <string name="settings_calendar_title">Calendar</string>
@ -93,6 +104,11 @@
<string name="attendee_status_invited">Events invitations</string> <string name="attendee_status_invited">Events invitations</string>
<string name="attendee_status_declined">Declined events</string> <string name="attendee_status_declined">Declined events</string>
<string name="calendar_sync_notification_channel_id" translatable="false">calendar-sync</string>
<string name="calendar_sync_notification_channel_name">Events sync service</string>
<string name="calendar_sync_notification_channel_description">Service used to synchronize the calendar events.</string>
<string name="calendar_sync_notification_title">Syncing calendar events…</string>
<!-- Weather --> <!-- Weather -->
<string name="settings_weather_title">Weather</string> <string name="settings_weather_title">Weather</string>
<string name="title_permission_location">Show the weather</string> <string name="title_permission_location">Show the weather</string>
@ -162,7 +178,7 @@
<string name="weather_provider_activity_subtitle">Select a weather provider from the list.\nA few providers need a free personal account,\nbut they are usually more accurate.</string> <string name="weather_provider_activity_subtitle">Select a weather provider from the list.\nA few providers need a free personal account,\nbut they are usually more accurate.</string>
<string name="location_access_notification_channel_id" translatable="false">location-access</string> <string name="location_access_notification_channel_id" translatable="false">location-access</string>
<string name="location_access_notification_channel_name">Background service</string> <string name="location_access_notification_channel_name">Weather update service</string>
<string name="location_access_notification_channel_description">Service used to update the weather based on the current location of the user.</string> <string name="location_access_notification_channel_description">Service used to update the weather based on the current location of the user.</string>
<string name="location_access_notification_title">Updating the weather…</string> <string name="location_access_notification_title">Updating the weather…</string>
<string name="location_access_notification_subtitle">We\'re updating the weather based on your current location.</string> <string name="location_access_notification_subtitle">We\'re updating the weather based on your current location.</string>
@ -326,6 +342,9 @@
<string name="nothing">Nothing</string> <string name="nothing">Nothing</string>
<string name="action_dismiss">Dismiss</string> <string name="action_dismiss">Dismiss</string>
<string name="action_accept">Accept</string> <string name="action_accept">Accept</string>
<string name="gestures_do_nothing">None</string>
<string name="song_info_format_activity_title">Song info format</string>
<string name="song_info_format_activity_subtitle">Change the visible song info</string>
<!-- More --> <!-- More -->
<string name="look_and_feel_header"><![CDATA[Look & feel]]></string> <string name="look_and_feel_header"><![CDATA[Look & feel]]></string>
@ -338,5 +357,4 @@
<string name="clock_settings_subtitle">Set size, color and time zones</string> <string name="clock_settings_subtitle">Set size, color and time zones</string>
<string name="layout_settings_subtitle">Widget spacing and tweaks</string> <string name="layout_settings_subtitle">Widget spacing and tweaks</string>
<string name="smart_content_header">Smart content</string> <string name="smart_content_header">Smart content</string>
<string name="font_family_settings_title">Font family</string>
</resources> </resources>