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

Add a welcome dialog #974

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
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
13 changes: 1 addition & 12 deletions cozy/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import platform
import sys
import threading
from pathlib import Path
from traceback import format_exception

import distro
Expand All @@ -12,8 +11,6 @@
from cozy.app_controller import AppController
from cozy.control.db import init_db
from cozy.control.mpris import MPRIS
from cozy.db.settings import Settings
from cozy.db.storage import Storage
from cozy.report import reporter
from cozy.ui.main_view import CozyUI
from cozy.ui.widgets.filter_list_box import FilterListBox
Expand All @@ -29,7 +26,7 @@ class Application(Adw.Application):
def __init__(self, pkgdatadir: str):
self.pkgdatadir = pkgdatadir

super().__init__(application_id='com.github.geigi.cozy')
super().__init__(application_id="com.github.geigi.cozy")
self.init_custom_widgets()

GLib.setenv("PULSE_PROP_media.role", "music", True)
Expand All @@ -52,14 +49,6 @@ def do_activate(self):
self.app_controller = AppController(self, main_window_builder, self.ui)

self.ui.activate(self.app_controller.library_view)

if Settings.get().first_start:
Settings.update(first_start=False).execute()

audiobooks_path = Path.home() / _("Audiobooks")
audiobooks_path.mkdir(exist_ok=True)
Storage.create(path=str(audiobooks_path), default=True)

self.add_window(self.ui.window)

if platform.system().lower() == "linux":
Expand Down
8 changes: 8 additions & 0 deletions cozy/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ def last_launched_version(self) -> str:
def last_launched_version(self, new_value: str):
self._settings.set_string("last-launched-version", new_value)

@property
def first_launch(self) -> bool:
return self._settings.get_boolean("first-launch")

@first_launch.setter
def first_launch(self, new_value: bool):
self._settings.set_boolean("first-launch", new_value)

@property
def rewind_duration(self) -> int:
return self._settings.get_int("rewind-duration")
Expand Down
24 changes: 14 additions & 10 deletions cozy/ui/main_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
from cozy.ui.book_detail_view import BookDetailView
from cozy.ui.library_view import LibraryView
from cozy.ui.preferences_window import PreferencesWindow
from cozy.ui.widgets.first_import_button import FirstImportButton
from cozy.ui.widgets.storages import ask_storage_location
from cozy.ui.widgets.welcome_dialog import WelcomeDialog
from cozy.view_model.playback_control_view_model import PlaybackControlViewModel
from cozy.view_model.playback_speed_view_model import PlaybackSpeedViewModel
from cozy.view_model.storages_view_model import StoragesViewModel
Expand Down Expand Up @@ -91,6 +92,8 @@ def __init_window(self):
self.drop_revealer: Gtk.Revealer = self.window_builder.get_object("drop_revealer")

self.navigation_view.add(BookDetailView())
if self.application_settings.first_launch:
WelcomeDialog().present(self.window)

self.window.present()

Expand Down Expand Up @@ -121,15 +124,17 @@ def set_hotkeys_enabled(self, enabled: bool) -> None:
action.set_enabled(enabled)

def __init_components(self):
path = self._settings.default_location.path if self._settings.storage_locations else None
self.import_button = FirstImportButton(self._set_audiobook_path, path)
self.get_object("welcome_status_page").set_child(self.import_button)
self.get_object("first_import_button").connect("clicked", self._on_choose_location_clicked)

if not self._player.loaded_book:
self.block_ui_buttons(True)

self._importer.add_listener(self._on_importer_event)

def _on_choose_location_clicked(self, _):
initial_path = self._settings.default_location.path if self._settings.storage_locations else None
ask_storage_location(self._set_audiobook_path, initial_path)

def create_action(
self,
name: str,
Expand Down Expand Up @@ -236,13 +241,13 @@ def check_for_tracks(self):
if books().count() < 1:
self.block_ui_buttons(True)

def scan(self, _, __):
def scan(self, *_):
thread = Thread(target=self._importer.scan, name="ScanMediaThread")
thread.start()

def auto_import(self):
if self.application_settings.autoscan:
self.scan(None, None)
self.scan()

def __on_hide_offline(self, action, value):
"""
Expand All @@ -266,13 +271,12 @@ def _on_drag_data_received(self, widget, value, *_):
thread.start()
return True

def _set_audiobook_path(self, path: str | None) -> None:
def _set_audiobook_path(self, path: str | None, default: bool = True) -> None:
if path is None:
return

self.import_button.disable()
self._storages_view_model.add_first_storage_location(path)
self.scan(None, None)
self.main_stack.set_visible_child_name("import")
self._storages_view_model.add_storage_location(path, default=default)
self.fs_monitor.init_offline_mode()

def on_close(self, widget, data=None):
Expand Down
1 change: 0 additions & 1 deletion cozy/ui/preferences_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ def __init__(self) -> None:
super().__init__()

error_reporting = ErrorReporting()
error_reporting.show_header(False)
self.user_feedback_preference_group.add(error_reporting)

self.storage_locations_view = StorageLocations()
Expand Down
5 changes: 3 additions & 2 deletions cozy/ui/widgets/book_card.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def do_snapshot(self, snapshot: Gtk.Snapshot) -> None:
context.stroke()


@Gtk.Template.from_resource('/com/github/geigi/cozy/ui/book_card.ui')
@Gtk.Template.from_resource("/com/github/geigi/cozy/ui/book_card.ui")
class BookCard(Gtk.FlowBoxChild):
__gtype_name__ = "BookCard"

Expand Down Expand Up @@ -112,7 +112,8 @@ def set_playing(self, is_playing):
self.play_button.set_playing(is_playing)

def update_progress(self):
self.play_button.progress = self.book.progress / self.book.duration
if self.book.duration:
self.play_button.progress = self.book.progress / self.book.duration

def reset(self) -> None:
self.book.last_played = 0
Expand Down
86 changes: 31 additions & 55 deletions cozy/ui/widgets/error_reporting.py
Original file line number Diff line number Diff line change
@@ -1,94 +1,70 @@
from gettext import gettext as _
from itertools import chain

import inject
from gi.repository import Gtk
from gi.repository import Adw, Gtk

from cozy.settings import ApplicationSettings

LEVELS = [
_("Disabled"),
_("Basic error reporting"),
_("Detailed error reporting"),
_("Detailed error reporting with import errors")
_("Detailed, with media types"),
]

LEVEL_DESCRIPTION = [
_("No error or crash reporting."),
_("The following information will be sent in case of an error or crash:")
_("The following information will be sent in case of an error or crash:"),
]

LEVEL_DETAILS = {
0: [],
1: [_("Which type of error occurred"),
LEVEL_DETAILS = [
[],
[
_("Which type of error occurred"),
_("Line of code where an error occurred"),
_("Cozy's version"), ],
2: [_("Linux distribution"),
_("Desktop environment")],
3: [_("Media type of files that Cozy couldn't import")]
}
_("Cozy's version"),
],
[_("Linux distribution"), _("Desktop environment")],
[_("Media type of files that Cozy couldn't import")],
]


@Gtk.Template.from_resource('/com/github/geigi/cozy/ui/error_reporting.ui')
@Gtk.Template.from_resource("/com/github/geigi/cozy/ui/error_reporting.ui")
class ErrorReporting(Gtk.Box):
__gtype_name__ = 'ErrorReporting'

level_label: Gtk.Label = Gtk.Template.Child()
description_label: Gtk.Label = Gtk.Template.Child()
details_label: Gtk.Label = Gtk.Template.Child()
header_box: Gtk.Box = Gtk.Template.Child()
__gtype_name__ = "ErrorReporting"

verbose_adjustment: Gtk.Adjustment = Gtk.Template.Child()
verbose_scale: Gtk.Scale = Gtk.Template.Child()
description: Adw.ActionRow = Gtk.Template.Child()
detail_combo: Adw.ComboRow = Gtk.Template.Child()

app_settings: ApplicationSettings = inject.attr(ApplicationSettings)

def __init__(self, **kwargs):
super().__init__(**kwargs)

self.__init_scale()
levels_list = Gtk.StringList(strings=LEVELS)
self.detail_combo.props.model = levels_list
self.detail_combo.connect("notify::selected-item", self._level_selected)

self._load_report_level()
self.__connect()

self.app_settings.add_listener(self._on_app_setting_changed)

def show_header(self, show: bool):
self.header_box.set_visible(show)

def _load_report_level(self):
level = self.app_settings.report_level
self.verbose_adjustment.set_value(level + 1)
self._update_ui_texts(level)

def __init_scale(self):
for i in range(1, 5):
self.verbose_scale.add_mark(i, Gtk.PositionType.RIGHT, None)
self.verbose_scale.set_round_digits(0)

def __connect(self):
self.verbose_adjustment.connect("value-changed", self._adjustment_changed)

def _adjustment_changed(self, adjustment: Gtk.Adjustment):
level = int(adjustment.get_value()) - 1
self.app_settings.report_level = level
self._update_ui_texts(level)

def _update_ui_texts(self, level: int):
self.level_label.set_text(LEVELS[level])
self._update_description(level)
self._update_details(level)
self.detail_combo.set_selected(level)

def _update_description(self, value):
detail_index = min(value, 1)
self.description_label.set_text(LEVEL_DESCRIPTION[detail_index])
def _level_selected(self, obj, param) -> None:
selected = obj.get_property(param.name).get_string()
index = LEVELS.index(selected)
self.app_settings.report_level = index
self._update_description(index)

def _update_details(self, value):
details = ""
for i in range(value + 1):
for line in LEVEL_DETAILS[i]:
details += f"• {line}\n"
self.details_label.set_text(details)
def _update_description(self, level: int):
self.description.set_title(LEVEL_DESCRIPTION[min(level, 1)])
details = "\n".join(["• " + i for i in chain(*LEVEL_DETAILS[: level + 1])])
self.description.set_subtitle(details)

def _on_app_setting_changed(self, event, _):
if event == "report-level":
self._load_report_level()

23 changes: 0 additions & 23 deletions cozy/ui/widgets/first_import_button.py

This file was deleted.

64 changes: 64 additions & 0 deletions cozy/ui/widgets/welcome_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import os.path
from pathlib import Path

import inject
from gi.repository import Adw, Gtk

from cozy.settings import ApplicationSettings
from cozy.ui.widgets.storages import ask_storage_location
from cozy.view_model.storages_view_model import StoragesViewModel


@Gtk.Template.from_resource("/com/github/geigi/cozy/ui/welcome_dialog.ui")
class WelcomeDialog(Adw.Dialog):
__gtype_name__ = "WelcomeDialog"

app_settings: ApplicationSettings = inject.attr(ApplicationSettings)
_storages_view_model: StoragesViewModel = inject.attr(StoragesViewModel)

carousel: Adw.Carousel = Gtk.Template.Child()
welcome_page: Adw.StatusPage = Gtk.Template.Child()
reporting_page: Gtk.Box = Gtk.Template.Child()
locations_page: Adw.StatusPage = Gtk.Template.Child()
create_directory_switch: Adw.SwitchRow = Gtk.Template.Child()
chooser_button_label: Adw.ButtonContent = Gtk.Template.Child()

def __init__(self):
super().__init__()
self._path = None
self._order = [self.welcome_page, self.reporting_page, self.locations_page]

@Gtk.Template.Callback()
def advance(self, *_):
self.carousel.scroll_to(self._order[int(self.carousel.get_position()) + 1], True)

@Gtk.Template.Callback()
def deny_reporting(self, _):
self.app_settings.report_level = 0
self.advance()

@Gtk.Template.Callback()
def accept_reporting(self, _):
self.advance()

@Gtk.Template.Callback()
def choose_directory(self, _):
ask_storage_location(self._ask_storage_location_callback, None)

def _ask_storage_location_callback(self, path):
self._path = path
self.chooser_button_label.set_label(os.path.basename(path))

@Gtk.Template.Callback()
def done(self, __chooser_button_label):
self.close()
self.app_settings.first_launch = False

if self.create_directory_switch.props.active:
audiobooks_dir = Path.home() / _("Audiobooks")
audiobooks_dir.mkdir(exist_ok=True)
self._storages_view_model.add_storage_location(str(audiobooks_dir), default=True)

inject.instance("MainWindow")._set_audiobook_path(self._path, default=False)
else:
inject.instance("MainWindow")._set_audiobook_path(self._path)
3 changes: 0 additions & 3 deletions cozy/view_model/settings_view_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ def __init__(self):

self._lock_ui: bool = False

if self._model.first_start:
self._importer.scan()

@property
def lock_ui(self) -> bool:
return self._lock_ui
Expand Down
Loading
Loading