diff --git a/assets/favicon.ico b/assets/favicon.ico index 477784b..ebfb471 100644 Binary files a/assets/favicon.ico and b/assets/favicon.ico differ diff --git a/assets/welcome.gif b/assets/welcome.gif new file mode 100644 index 0000000..53df771 Binary files /dev/null and b/assets/welcome.gif differ diff --git a/classes/app.py b/classes/app.py index 44cf9d5..d5114dd 100644 --- a/classes/app.py +++ b/classes/app.py @@ -10,6 +10,7 @@ from classes.frames.devices import FrameDevices from classes.frames.saves import FrameSaves from classes.frames.settings import FrameSettings from classes.frames.errors import FrameErrorConnection, FrameErrorSavesFolder, FrameErrorUnconfigured +from classes.toplevel.welcome import ToplevelWelcome from modules.theme_titlebar import theme_title_bar from modules.utils import configGet, get_string_mode, use_dark_mode @@ -92,6 +93,10 @@ class App(ThemedTk): # self.setup_button = ttk.Button(self, text="Set up", style="Accent.TButton", width=10, command=self.open_window_config) # self.setup_button.grid(column=1, row=1, padx=9, pady=9, sticky=N) # return + + if configGet("first_run") is True: + self.welcome_window = ToplevelWelcome(self) + self.welcome_window.grab_set() self.frame_sidebar = ThemedFrame(self) self.frame_sidebar.grid(column=0, row=0, columnspan=1, sticky=N+S+W+E) diff --git a/classes/custom/image_label.py b/classes/custom/image_label.py new file mode 100644 index 0000000..0b59cae --- /dev/null +++ b/classes/custom/image_label.py @@ -0,0 +1,40 @@ +import tkinter as tk +from PIL import Image, ImageTk +from itertools import count, cycle + +class ImageLabel(tk.Label): + """ + A Label that displays images, and plays them if they are gifs + :im: A PIL Image instance or a string filename + """ + def load(self, im): + if isinstance(im, str): + im = Image.open(im) + frames = [] + + try: + for i in count(1): + frames.append(ImageTk.PhotoImage(im.copy())) + im.seek(i) + except EOFError: + pass + self.frames = cycle(frames) + + try: + self.delay = im.info['duration'] + except: + self.delay = 100 + + if len(frames) == 1: + self.config(image=next(self.frames)) + else: + self.next_frame() + + def unload(self): + self.config(image=None) + self.frames = None + + def next_frame(self): + if self.frames: + self.config(image=next(self.frames)) + self.after(self.delay, self.next_frame) \ No newline at end of file diff --git a/classes/custom/themed_frame.py b/classes/custom/themed_frame.py index e951a41..ca4596b 100644 --- a/classes/custom/themed_frame.py +++ b/classes/custom/themed_frame.py @@ -1,5 +1,4 @@ -from ttkthemes import ThemedTk -from typing import Union +from tkinter import Misc import sv_ttk from tkinter.ttk import Frame @@ -7,7 +6,7 @@ from modules.utils import get_string_mode class ThemedFrame(Frame): - def __init__(self, master: ThemedTk, **kwargs) -> None: + def __init__(self, master: Misc, **kwargs) -> None: super().__init__(master, **kwargs) diff --git a/classes/custom/themed_toplevel.py b/classes/custom/themed_toplevel.py new file mode 100644 index 0000000..04b03be --- /dev/null +++ b/classes/custom/themed_toplevel.py @@ -0,0 +1,13 @@ +from tkinter import Misc, Toplevel +import sv_ttk +from modules.theme_titlebar import theme_title_bar + +from modules.utils import get_string_mode, use_dark_mode + +class ThemedToplevel(Toplevel): + + def __init__(self, master: Misc, **kwargs) -> None: + + super().__init__(master, **kwargs) + + sv_ttk.set_theme(get_string_mode()) \ No newline at end of file diff --git a/classes/toplevel/welcome.py b/classes/toplevel/welcome.py new file mode 100644 index 0000000..61cf162 --- /dev/null +++ b/classes/toplevel/welcome.py @@ -0,0 +1,60 @@ +from os import path +from tkinter import CENTER, END, E, Image, IntVar, N, S, PhotoImage, Toplevel, W, messagebox, ttk + +import requests +import sv_ttk +from classes.custom.image_label import ImageLabel + +from classes.custom.themed_toplevel import ThemedToplevel +from modules.logger import logger +from modules.theme_titlebar import theme_title_bar +from modules.utils import configGet, configSet, use_dark_mode + + +class ToplevelWelcome(ThemedToplevel): + + def __init__(self, parent): + + super().__init__(parent) + + self.window_width = 380 + self.window_height = 350 + + self.screen_width = self.winfo_screenwidth() + self.screen_height = self.winfo_screenheight() + + self.center_x = int(self.screen_width/2 - self.window_width / 2) + self.center_y = int(self.screen_height/2 - self.window_height / 2) + + self.title("Welcome to Stardew Sync") + self.geometry(f'{self.window_width}x{self.window_height}+{self.center_x}+{self.center_y}') + + self.resizable(False, True) + + sv_ttk.init_theme(self) + + if use_dark_mode(): + theme_title_bar(self, mode="dark") + self.update() + + self.iconbitmap(path.join("assets", "favicon.ico")) + self.focus_set() + + self.grid_columnconfigure(0, weight=1) + + self.welcome_pic = ImageLabel(self) + self.welcome_pic.grid(column=0, row=0, pady=20) + self.welcome_pic.load(path.join("assets", "welcome.gif")) + + self.welcome_text = ttk.Label(self, text="Welcome to Stardew Sync", font=("SunValleyBodyFont", 14)) + self.welcome_text.grid(column=0, row=1, pady=10) + + self.welcome_subtext = ttk.Label(self, text="This small open-source application will help you\nto synchronize your Stardew Valley save files\nbetween all your devices", justify=CENTER) + self.welcome_subtext.grid(column=0, row=2) + + self.welcome_button = ttk.Button(self, text="Begin", style="Accent.TButton", width=10, command=self.acknowledged) + self.welcome_button.grid(column=0, row=3, pady=20) + + def acknowledged(self): + configSet(["first_run"], False) + self.destroy() \ No newline at end of file diff --git a/config.json b/config.json index dc6c571..a80f29e 100644 --- a/config.json +++ b/config.json @@ -4,5 +4,6 @@ "allow_self_signed": false, "saves_location": null, "dark_mode": false, - "dark_mode_auto": true + "dark_mode_auto": true, + "first_run": true } \ No newline at end of file diff --git a/main.py b/main.py index 8f9757c..4a9d6d5 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,20 @@ +from os import path from classes.app import App +from modules.utils import jsonSave + +if not path.exists("config.json"): + jsonSave( + { + "address": None, + "apikey": None, + "allow_self_signed": False, + "saves_location": None, + "dark_mode": False, + "dark_mode_auto": True, + "first_run": True + }, + "config.json" + ) if __name__ == "__main__":