Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(player): Add custom buttons #196

Merged
merged 3 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions app/src/main/assets/aniyomi.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
aniyomi = {}
function aniyomi.show_text(text)
mp.set_property("user-data/aniyomi/show_text", text)
end
function aniyomi.hide_ui()
mp.set_property("user-data/aniyomi/toggle_ui", "hide")
end
function aniyomi.show_ui()
mp.set_property("user-data/aniyomi/toggle_ui", "show")
end
function aniyomi.toggle_ui()
mp.set_property("user-data/aniyomi/toggle_ui", "toggle")
end
function aniyomi.show_subtitle_settings()
mp.set_property("user-data/aniyomi/show_panel", "subtitle_settings")
end
function aniyomi.show_subtitle_delay()
mp.set_property("user-data/aniyomi/show_panel", "subtitle_delay")
end
function aniyomi.show_audio_delay()
mp.set_property("user-data/aniyomi/show_panel", "audio_delay")
end
function aniyomi.show_video_filters()
mp.set_property("user-data/aniyomi/show_panel", "video_filters")
end
function aniyomi.set_button_title(text)
mp.set_property("user-data/aniyomi/set_button_title", text)
end
function aniyomi.reset_button_title()
mp.set_property("user-data/aniyomi/reset_button_title", "unused")
end
function aniyomi.previous_episode()
mp.set_property("user-data/aniyomi/switch_episode", "p")
end
function aniyomi.next_episode()
mp.set_property("user-data/aniyomi/switch_episode", "n")
end
function aniyomi.int_picker(title, name_format, start, stop, step, property)
mp.set_property("user-data/aniyomi/launch_int_picker", title .. "|" .. name_format .. "|" .. start .. "|" .. stop .. "|" .. step .. "|" .. property)
end
function aniyomi.pause()
mp.set_property("user-data/aniyomi/pause", "pause")
end
function aniyomi.unpause()
mp.set_property("user-data/aniyomi/pause", "unpause")
end
function aniyomi.pauseunpause()
mp.set_property("user-data/aniyomi/pause", "pauseunpause")
end
function aniyomi.seek_to_with_text(value, text)
mp.set_property("user-data/aniyomi/seek_with_text", value .. "|" .. text)
end
function aniyomi.hide_button()
mp.set_property("user-data/aniyomi/toggle_button", "h")
end
function aniyomi.show_button()
mp.set_property("user-data/aniyomi/toggle_button", "s")
end
function aniyomi.left_seek_by(value)
mp.set_property("user-data/aniyomi/seek_by", "l|" .. value)
end
function aniyomi.right_seek_by(value)
mp.set_property("user-data/aniyomi/seek_by", "r|" .. value)
end
return aniyomi
16 changes: 16 additions & 0 deletions app/src/main/java/eu/kanade/domain/DomainModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import mihon.domain.upcoming.anime.interactor.GetUpcomingAnime
import mihon.domain.upcoming.manga.interactor.GetUpcomingManga
import tachiyomi.data.category.anime.AnimeCategoryRepositoryImpl
import tachiyomi.data.category.manga.MangaCategoryRepositoryImpl
import tachiyomi.data.custombutton.CustomButtonRepositoryImpl
import tachiyomi.data.entries.anime.AnimeRepositoryImpl
import tachiyomi.data.entries.manga.MangaRepositoryImpl
import tachiyomi.data.history.anime.AnimeHistoryRepositoryImpl
Expand Down Expand Up @@ -105,6 +106,13 @@ import tachiyomi.domain.category.manga.interactor.SetMangaDisplayMode
import tachiyomi.domain.category.manga.interactor.SetSortModeForMangaCategory
import tachiyomi.domain.category.manga.interactor.UpdateMangaCategory
import tachiyomi.domain.category.manga.repository.MangaCategoryRepository
import tachiyomi.domain.custombuttons.interactor.CreateCustomButton
import tachiyomi.domain.custombuttons.interactor.DeleteCustomButton
import tachiyomi.domain.custombuttons.interactor.GetCustomButtons
import tachiyomi.domain.custombuttons.interactor.ReorderCustomButton
import tachiyomi.domain.custombuttons.interactor.ToggleFavoriteCustomButton
import tachiyomi.domain.custombuttons.interactor.UpdateCustomButton
import tachiyomi.domain.custombuttons.repository.CustomButtonRepository
import tachiyomi.domain.entries.anime.interactor.AnimeFetchInterval
import tachiyomi.domain.entries.anime.interactor.GetAnime
import tachiyomi.domain.entries.anime.interactor.GetAnimeByUrlAndSourceId
Expand Down Expand Up @@ -369,5 +377,13 @@ class DomainModule : InjektModule {
addFactory { DeleteMangaExtensionRepo(get()) }
addFactory { ReplaceMangaExtensionRepo(get()) }
addFactory { UpdateMangaExtensionRepo(get(), get()) }

addSingletonFactory<CustomButtonRepository> { CustomButtonRepositoryImpl(get()) }
addFactory { CreateCustomButton(get()) }
addFactory { DeleteCustomButton(get()) }
addFactory { GetCustomButtons(get()) }
addFactory { UpdateCustomButton(get()) }
addFactory { ReorderCustomButton(get()) }
addFactory { ToggleFavoriteCustomButton(get()) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ object PlayerSettingsGesturesScreen : SearchableSettings {
}

@Composable
private fun SkipIntroLengthDialog(
fun SkipIntroLengthDialog(
initialSkipIntroLength: Int,
onDismissRequest: () -> Unit,
onValueChanged: (skipIntroLength: Int) -> Unit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.compose.material.icons.outlined.Memory
import androidx.compose.material.icons.outlined.PlayCircleOutline
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material.icons.outlined.Subtitles
import androidx.compose.material.icons.outlined.Terminal
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TopAppBarDefaults
Expand All @@ -37,6 +38,7 @@ import dev.icerock.moko.resources.StringResource
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarActions
import eu.kanade.presentation.more.settings.screen.SettingsSearchScreen
import eu.kanade.presentation.more.settings.screen.player.custombutton.PlayerSettingsCustomButtonScreen
import eu.kanade.presentation.more.settings.widget.TextPreferenceWidget
import eu.kanade.presentation.util.LocalBackPress
import eu.kanade.presentation.util.Screen
Expand Down Expand Up @@ -199,6 +201,12 @@ object PlayerSettingsMainScreen : Screen() {
icon = Icons.Outlined.Audiotrack,
screen = PlayerSettingsAudioScreen,
),
Item(
titleRes = MR.strings.pref_player_custom_button,
subtitleRes = MR.strings.pref_player_custom_button_summary,
icon = Icons.Outlined.Terminal,
screen = PlayerSettingsCustomButtonScreen,
),
Item(
titleRes = MR.strings.pref_player_advanced,
subtitleRes = MR.strings.pref_player_advanced_summary,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package eu.kanade.presentation.more.settings.screen.player.custombutton

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.util.fastMap
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.presentation.more.settings.screen.player.custombutton.components.CustomButtonCreateDialog
import eu.kanade.presentation.more.settings.screen.player.custombutton.components.CustomButtonDeleteDialog
import eu.kanade.presentation.more.settings.screen.player.custombutton.components.CustomButtonEditDialog
import eu.kanade.presentation.more.settings.screen.player.custombutton.components.CustomButtonScreen
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.collectLatest
import tachiyomi.domain.custombuttons.model.CustomButtonUpdate
import tachiyomi.presentation.core.screens.LoadingScreen

object PlayerSettingsCustomButtonScreen : Screen() {

@Composable
override fun Content() {
val context = LocalContext.current
val navigator = LocalNavigator.currentOrThrow
val uriHandler = LocalUriHandler.current
val screenModel = rememberScreenModel { PlayerSettingsCustomButtonScreenModel() }

val state by screenModel.state.collectAsState()

if (state is CustomButtonScreenState.Loading) {
LoadingScreen()
return
}

val successState = state as CustomButtonScreenState.Success

CustomButtonScreen(
state = successState,
onClickFAQ = { uriHandler.openUri("https://aniyomi.org/docs/guides/player-settings/custom-buttons") },
onClickCreate = { screenModel.showDialog(CustomButtonDialog.Create) },
onClickPrimary = { screenModel.togglePrimaryButton(it) },
onClickEdit = { screenModel.showDialog(CustomButtonDialog.Edit(it)) },
onClickDelete = { screenModel.showDialog(CustomButtonDialog.Delete(it)) },
onClickMoveUp = screenModel::moveUp,
onClickMoveDown = screenModel::moveDown,
navigateUp = navigator::pop,
)

when (val dialog = successState.dialog) {
null -> {}
CustomButtonDialog.Create -> {
CustomButtonCreateDialog(
onDismissRequest = screenModel::dismissDialog,
onCreate = screenModel::createCustomButton,
buttonNames = successState.customButtons.fastMap { it.name }.toImmutableList(),
)
}
is CustomButtonDialog.Delete -> {
CustomButtonDeleteDialog(
onDismissRequest = screenModel::dismissDialog,
onDelete = { screenModel.deleteCustomButton(dialog.customButton) },
buttonTitle = dialog.customButton.name,
)
}
is CustomButtonDialog.Edit -> {
CustomButtonEditDialog(
onDismissRequest = screenModel::dismissDialog,
onEdit = { title, content, longPressContent, onStartup ->
screenModel.editCustomButton(
CustomButtonUpdate(
id = dialog.customButton.id,
name = title,
sortIndex = dialog.customButton.sortIndex,
content = content,
longPressContent = longPressContent,
onStartup = onStartup,
),
)
},
buttonNames = (successState.customButtons - dialog.customButton).fastMap {
it.name
}.toImmutableList(),
initialState = dialog.customButton,
)
}
}

LaunchedEffect(Unit) {
screenModel.events.collectLatest { event ->
if (event is CustomButtonEvent.LocalizedMessage) {
context.toast(event.stringRes)
}
}
}
}
}
Loading
Loading