From 2dc97437dd983d7775764b43fe4f7470f1908d64 Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Tue, 18 Nov 2025 18:07:15 +0100 Subject: [PATCH] feat; added workout screen lock --- PYTHON/screen_locker/install_autostart.sh | 52 ++ PYTHON/screen_locker/install_systemd.sh | 30 + PYTHON/screen_locker/remove_autostart.sh | 33 ++ PYTHON/screen_locker/remove_systemd.sh | 19 + PYTHON/screen_locker/screen_lock.py | 596 ++++++++++++++++++++ PYTHON/screen_locker/workout-locker.service | 14 + 6 files changed, 744 insertions(+) create mode 100755 PYTHON/screen_locker/install_autostart.sh create mode 100755 PYTHON/screen_locker/install_systemd.sh create mode 100755 PYTHON/screen_locker/remove_autostart.sh create mode 100755 PYTHON/screen_locker/remove_systemd.sh create mode 100755 PYTHON/screen_locker/screen_lock.py create mode 100644 PYTHON/screen_locker/workout-locker.service diff --git a/PYTHON/screen_locker/install_autostart.sh b/PYTHON/screen_locker/install_autostart.sh new file mode 100755 index 0000000..0a5b5ca --- /dev/null +++ b/PYTHON/screen_locker/install_autostart.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# Script to add screen locker to i3 autostart +# This will run the workout screen locker on system startup + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +SCREEN_LOCK_PATH="$SCRIPT_DIR/screen_lock.py" +I3_CONFIG="$HOME/.config/i3/config" + +# Check if screen_lock.py exists +if [ ! -f "$SCREEN_LOCK_PATH" ]; then + echo "Error: screen_lock.py not found at $SCREEN_LOCK_PATH" + exit 1 +fi + +# Make sure screen_lock.py is executable +chmod +x "$SCREEN_LOCK_PATH" + +# Check if i3 config exists +if [ ! -f "$I3_CONFIG" ]; then + echo "Error: i3 config not found at $I3_CONFIG" + echo "Please create i3 config first or specify correct path" + exit 1 +fi + +# Check if autostart line already exists +if grep -q "exec.*screen_lock.py" "$I3_CONFIG"; then + echo "Screen locker autostart already configured in i3 config" + echo "Current line:" + grep "exec.*screen_lock.py" "$I3_CONFIG" + read -p "Do you want to replace it? (y/n) " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + # Remove old line + sed -i '/exec.*screen_lock\.py/d' "$I3_CONFIG" + else + echo "Keeping existing configuration" + exit 0 + fi +fi + +# Add autostart line to i3 config +echo "" >> "$I3_CONFIG" +echo "# Workout screen locker on startup (demo mode)" >> "$I3_CONFIG" +echo "exec --no-startup-id python3 $SCREEN_LOCK_PATH" >> "$I3_CONFIG" + +echo "✓ Screen locker added to i3 autostart (demo mode)" +echo "✓ Configuration added to: $I3_CONFIG" +echo "" +echo "The screen locker will run on next i3 restart/login" +echo "" +echo "To test now, run: i3-msg restart" +echo "To switch to production mode later, edit $I3_CONFIG and add --production flag" diff --git a/PYTHON/screen_locker/install_systemd.sh b/PYTHON/screen_locker/install_systemd.sh new file mode 100755 index 0000000..ac8d973 --- /dev/null +++ b/PYTHON/screen_locker/install_systemd.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# Install workout locker as a systemd user service + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +SERVICE_FILE="$SCRIPT_DIR/workout-locker.service" +USER_SERVICE_DIR="$HOME/.config/systemd/user" +SERVICE_NAME="workout-locker.service" + +# Create user systemd directory if it doesn't exist +mkdir -p "$USER_SERVICE_DIR" + +# Copy service file to user systemd directory +cp "$SERVICE_FILE" "$USER_SERVICE_DIR/$SERVICE_NAME" + +# Update the ExecStart path in the service file to use absolute path +sed -i "s|ExecStart=/usr/bin/python3.*|ExecStart=/usr/bin/python3 $SCRIPT_DIR/screen_lock.py|" "$USER_SERVICE_DIR/$SERVICE_NAME" + +# Reload systemd daemon +systemctl --user daemon-reload + +# Enable the service to start on login +systemctl --user enable "$SERVICE_NAME" + +echo "✓ Workout locker service installed" +echo "✓ Service will start automatically on next login" +echo "" +echo "To start now: systemctl --user start workout-locker" +echo "To check status: systemctl --user status workout-locker" +echo "To stop: systemctl --user stop workout-locker" +echo "To disable autostart: systemctl --user disable workout-locker" diff --git a/PYTHON/screen_locker/remove_autostart.sh b/PYTHON/screen_locker/remove_autostart.sh new file mode 100755 index 0000000..2507ffc --- /dev/null +++ b/PYTHON/screen_locker/remove_autostart.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Script to remove screen locker from i3 autostart + +I3_CONFIG="$HOME/.config/i3/config" + +# Check if i3 config exists +if [ ! -f "$I3_CONFIG" ]; then + echo "Error: i3 config not found at $I3_CONFIG" + exit 1 +fi + +# Check if autostart line exists +if ! grep -q "exec.*screen_lock.py" "$I3_CONFIG"; then + echo "Screen locker autostart not found in i3 config" + exit 0 +fi + +# Show what will be removed +echo "Found screen locker configuration:" +grep -B1 "exec.*screen_lock.py" "$I3_CONFIG" +echo "" + +read -p "Remove screen locker from autostart? (y/n) " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]]; then + # Remove the autostart lines + sed -i '/# Workout screen locker on startup/d' "$I3_CONFIG" + sed -i '/exec.*screen_lock\.py/d' "$I3_CONFIG" + echo "✓ Screen locker removed from i3 autostart" + echo "Changes will take effect on next i3 restart" +else + echo "Cancelled" +fi diff --git a/PYTHON/screen_locker/remove_systemd.sh b/PYTHON/screen_locker/remove_systemd.sh new file mode 100755 index 0000000..a024938 --- /dev/null +++ b/PYTHON/screen_locker/remove_systemd.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Remove workout locker systemd service + +SERVICE_NAME="workout-locker.service" +USER_SERVICE_DIR="$HOME/.config/systemd/user" + +# Stop the service if running +systemctl --user stop "$SERVICE_NAME" 2>/dev/null + +# Disable the service +systemctl --user disable "$SERVICE_NAME" 2>/dev/null + +# Remove service file +rm -f "$USER_SERVICE_DIR/$SERVICE_NAME" + +# Reload systemd daemon +systemctl --user daemon-reload + +echo "✓ Workout locker service removed" diff --git a/PYTHON/screen_locker/screen_lock.py b/PYTHON/screen_locker/screen_lock.py new file mode 100755 index 0000000..ddbfbaf --- /dev/null +++ b/PYTHON/screen_locker/screen_lock.py @@ -0,0 +1,596 @@ +#!/usr/bin/env python3 +""" +Screen locker with workout verification for Arch Linux / i3wm +Requires user to log their workout to unlock the screen. +""" + +import tkinter as tk +import time +import sys +import re +import json +import os +from datetime import datetime + + +class ScreenLocker: + def __init__(self, demo_mode=True): + # Set up log file path + script_dir = os.path.dirname(os.path.abspath(__file__)) + self.log_file = os.path.join(script_dir, 'workout_log.json') + + # Check if already logged today + if self.has_logged_today(): + print("Workout already logged today. Skipping screen lock.") + sys.exit(0) + + self.root = tk.Tk() + self.root.title("Workout Locker" + (" [DEMO MODE]" if demo_mode else "")) + self.demo_mode = demo_mode + self.lockout_time = 10 if demo_mode else 1800 # 10 seconds for demo, 30 minutes for production + self.workout_data = {} + + # Get total screen dimensions across all monitors + screen_width = self.root.winfo_screenwidth() + screen_height = self.root.winfo_screenheight() + + # Override redirect to bypass window manager (needed for multi-monitor spanning) + self.root.overrideredirect(True) + + # Position window at 0,0 and span all monitors + self.root.geometry(f'{screen_width}x{screen_height}+0+0') + + # Make window fullscreen and on top + self.root.attributes('-fullscreen', True) + self.root.attributes('-topmost', True) + self.root.configure(bg='#1a1a1a', cursor='arrow') + + if demo_mode: + # Demo mode: only close button allowed + # Add close button in top-left corner + close_btn = tk.Button( + self.root, + text="✕ Close Demo", + font=('Arial', 12), + bg='#ff4444', + fg='white', + command=self.close, + cursor='hand2' + ) + close_btn.place(x=10, y=10) + + # Create main container + self.container = tk.Frame(self.root, bg='#1a1a1a') + self.container.place(relx=0.5, rely=0.5, anchor='center') + + # Start with initial question + self.ask_workout_done() + + # Force window to update and grab input after everything is set up + self.root.update_idletasks() + self.root.focus_force() + self.root.grab_set_global() + + def clear_container(self): + for widget in self.container.winfo_children(): + widget.destroy() + + def ask_workout_done(self): + self.clear_container() + + question = tk.Label( + self.container, + text="Did you work out today?", + font=('Arial', 36, 'bold'), + fg='white', + bg='#1a1a1a' + ) + question.pack(pady=30) + + button_frame = tk.Frame(self.container, bg='#1a1a1a') + button_frame.pack(pady=20) + + yes_btn = tk.Button( + button_frame, + text="YES", + font=('Arial', 24, 'bold'), + bg='#00aa00', + fg='white', + width=10, + command=self.ask_workout_type, + cursor='hand2' if self.demo_mode else '' + ) + yes_btn.pack(side='left', padx=20) + + no_btn = tk.Button( + button_frame, + text="NO", + font=('Arial', 24, 'bold'), + bg='#aa0000', + fg='white', + width=10, + command=self.lockout, + cursor='hand2' if self.demo_mode else '' + ) + no_btn.pack(side='left', padx=20) + + def lockout(self): + self.clear_container() + + self.lockout_label = tk.Label( + self.container, + text=f"Go work out!\nLocked for {self.lockout_time} seconds", + font=('Arial', 48, 'bold'), + fg='#ff4444', + bg='#1a1a1a' + ) + self.lockout_label.pack(pady=30) + + self.countdown_label = tk.Label( + self.container, + text=str(self.lockout_time), + font=('Arial', 120, 'bold'), + fg='white', + bg='#1a1a1a' + ) + self.countdown_label.pack(pady=30) + + self.remaining_time = self.lockout_time + self.update_lockout_countdown() + + def update_lockout_countdown(self): + if self.remaining_time > 0: + self.countdown_label.config(text=str(self.remaining_time)) + self.remaining_time -= 1 + self.root.after(1000, self.update_lockout_countdown) + else: + self.ask_workout_done() + + def ask_workout_type(self): + self.clear_container() + + question = tk.Label( + self.container, + text="What type of workout?", + font=('Arial', 36, 'bold'), + fg='white', + bg='#1a1a1a' + ) + question.pack(pady=30) + + button_frame = tk.Frame(self.container, bg='#1a1a1a') + button_frame.pack(pady=20) + + running_btn = tk.Button( + button_frame, + text="RUNNING", + font=('Arial', 24, 'bold'), + bg='#0066cc', + fg='white', + width=15, + command=self.ask_running_details, + cursor='hand2' if self.demo_mode else '' + ) + running_btn.pack(side='left', padx=20) + + strength_btn = tk.Button( + button_frame, + text="STRENGTH", + font=('Arial', 24, 'bold'), + bg='#cc6600', + fg='white', + width=15, + command=self.ask_strength_details, + cursor='hand2' if self.demo_mode else '' + ) + strength_btn.pack(side='left', padx=20) + + def ask_running_details(self): + self.clear_container() + self.workout_data['type'] = 'running' + + title = tk.Label( + self.container, + text="Running Details", + font=('Arial', 36, 'bold'), + fg='white', + bg='#1a1a1a' + ) + title.pack(pady=20) + + # Distance + dist_frame = tk.Frame(self.container, bg='#1a1a1a') + dist_frame.pack(pady=10) + tk.Label(dist_frame, text="Distance (km):", font=('Arial', 20), fg='white', bg='#1a1a1a').pack(side='left', padx=10) + self.distance_entry = tk.Entry(dist_frame, font=('Arial', 20), width=10) + self.distance_entry.pack(side='left', padx=10) + + # Time + time_frame = tk.Frame(self.container, bg='#1a1a1a') + time_frame.pack(pady=10) + tk.Label(time_frame, text="Time (minutes):", font=('Arial', 20), fg='white', bg='#1a1a1a').pack(side='left', padx=10) + self.time_entry = tk.Entry(time_frame, font=('Arial', 20), width=10) + self.time_entry.pack(side='left', padx=10) + + # Pace + pace_frame = tk.Frame(self.container, bg='#1a1a1a') + pace_frame.pack(pady=10) + tk.Label(pace_frame, text="Pace (min/km):", font=('Arial', 20), fg='white', bg='#1a1a1a').pack(side='left', padx=10) + self.pace_entry = tk.Entry(pace_frame, font=('Arial', 20), width=10) + self.pace_entry.pack(side='left', padx=10) + + # Timer countdown label + self.timer_label = tk.Label( + self.container, + text="", + font=('Arial', 16), + fg='#ffaa00', + bg='#1a1a1a' + ) + self.timer_label.pack(pady=10) + + self.submit_btn = tk.Button( + self.container, + text="SUBMIT (locked)", + font=('Arial', 24, 'bold'), + bg='#666666', + fg='white', + width=15, + state='disabled', + cursor='hand2' if self.demo_mode else '' + ) + self.submit_btn.pack(pady=10) + + # Back button + back_btn = tk.Button( + self.container, + text="← BACK", + font=('Arial', 18), + bg='#666666', + fg='white', + width=15, + command=self.ask_workout_type, + cursor='hand2' if self.demo_mode else '' + ) + back_btn.pack(pady=10) + + # Start 30 second timer + self.submit_unlock_time = 30 + self.entries_to_check = [self.distance_entry, self.time_entry, self.pace_entry] + self.submit_command = self.verify_running_data + self.update_submit_timer() + + def verify_running_data(self): + try: + distance = float(self.distance_entry.get()) + time_mins = float(self.time_entry.get()) + pace = float(self.pace_entry.get()) + + # Sanity checks + if distance <= 0 or distance > 100: + self.show_error("Distance seems unrealistic (0-100 km)") + return + + if time_mins <= 0 or time_mins > 600: + self.show_error("Time seems unrealistic (0-600 minutes)") + return + + if pace <= 0 or pace > 20: + self.show_error("Pace seems unrealistic (0-20 min/km)") + return + + # Calculate expected pace and check if close enough + expected_pace = time_mins / distance + pace_diff = abs(pace - expected_pace) + tolerance = expected_pace * 0.15 # 15% tolerance + + if pace_diff > tolerance: + self.show_error(f"Pace doesn't match! Expected ~{expected_pace:.2f} min/km, got {pace:.2f}") + return + + # Data looks good + self.unlock_screen() + + except ValueError: + self.show_error("Please enter valid numbers") + + def ask_strength_details(self): + self.clear_container() + self.workout_data['type'] = 'strength' + + title = tk.Label( + self.container, + text="Strength Training Details", + font=('Arial', 36, 'bold'), + fg='white', + bg='#1a1a1a' + ) + title.pack(pady=20) + + # Exercises + ex_frame = tk.Frame(self.container, bg='#1a1a1a') + ex_frame.pack(pady=10) + tk.Label(ex_frame, text="Exercises (comma-separated):", font=('Arial', 18), fg='white', bg='#1a1a1a').pack(side='left', padx=10) + self.exercises_entry = tk.Entry(ex_frame, font=('Arial', 18), width=30) + self.exercises_entry.pack(side='left', padx=10) + + # Sets per exercise + sets_frame = tk.Frame(self.container, bg='#1a1a1a') + sets_frame.pack(pady=10) + tk.Label(sets_frame, text="Sets per exercise (comma-separated):", font=('Arial', 18), fg='white', bg='#1a1a1a').pack(side='left', padx=10) + self.sets_entry = tk.Entry(sets_frame, font=('Arial', 18), width=20) + self.sets_entry.pack(side='left', padx=10) + + # Reps per set + reps_frame = tk.Frame(self.container, bg='#1a1a1a') + reps_frame.pack(pady=10) + tk.Label(reps_frame, text="Reps per set (comma-separated):", font=('Arial', 18), fg='white', bg='#1a1a1a').pack(side='left', padx=10) + self.reps_entry = tk.Entry(reps_frame, font=('Arial', 18), width=20) + self.reps_entry.pack(side='left', padx=10) + + # Weights + weights_frame = tk.Frame(self.container, bg='#1a1a1a') + weights_frame.pack(pady=10) + tk.Label(weights_frame, text="Weight per exercise in kg (comma-separated):", font=('Arial', 18), fg='white', bg='#1a1a1a').pack(side='left', padx=10) + self.weights_entry = tk.Entry(weights_frame, font=('Arial', 18), width=20) + self.weights_entry.pack(side='left', padx=10) + + # Total weight lifted + total_frame = tk.Frame(self.container, bg='#1a1a1a') + total_frame.pack(pady=10) + tk.Label(total_frame, text="Total weight lifted (kg):", font=('Arial', 18), fg='white', bg='#1a1a1a').pack(side='left', padx=10) + self.total_weight_entry = tk.Entry(total_frame, font=('Arial', 18), width=15) + self.total_weight_entry.pack(side='left', padx=10) + + # Timer countdown label + self.timer_label = tk.Label( + self.container, + text="", + font=('Arial', 16), + fg='#ffaa00', + bg='#1a1a1a' + ) + self.timer_label.pack(pady=10) + + self.submit_btn = tk.Button( + self.container, + text="SUBMIT (locked)", + font=('Arial', 24, 'bold'), + bg='#666666', + fg='white', + width=15, + state='disabled', + cursor='hand2' if self.demo_mode else '' + ) + self.submit_btn.pack(pady=10) + + # Back button + back_btn = tk.Button( + self.container, + text="← BACK", + font=('Arial', 18), + bg='#666666', + fg='white', + width=15, + command=self.ask_workout_type, + cursor='hand2' if self.demo_mode else '' + ) + back_btn.pack(pady=10) + + # Start 30 second timer + self.submit_unlock_time = 30 + self.entries_to_check = [self.exercises_entry, self.sets_entry, self.reps_entry, self.weights_entry, self.total_weight_entry] + self.submit_command = self.verify_strength_data + self.update_submit_timer() + + def verify_strength_data(self): + try: + exercises = [e.strip() for e in self.exercises_entry.get().split(',')] + sets = [int(s.strip()) for s in self.sets_entry.get().split(',')] + reps = [int(r.strip()) for r in self.reps_entry.get().split(',')] + weights = [float(w.strip()) for w in self.weights_entry.get().split(',')] + total_weight = float(self.total_weight_entry.get()) + + # Check all lists have same length + if not (len(exercises) == len(sets) == len(reps) == len(weights)): + self.show_error("Number of exercises, sets, reps, and weights must match") + return + + # Check for empty or lazy entries + if any(len(ex) < 3 for ex in exercises): + self.show_error("Exercise names too short - be specific") + return + + # Sanity checks + if any(s < 1 or s > 20 for s in sets): + self.show_error("Sets should be between 1-20") + return + + if any(r < 1 or r > 100 for r in reps): + self.show_error("Reps should be between 1-100") + return + + if any(w < 0 or w > 500 for w in weights): + self.show_error("Weights should be between 0-500 kg") + return + + # Calculate expected total weight + expected_total = sum(sets[i] * reps[i] * weights[i] for i in range(len(exercises))) + weight_diff = abs(total_weight - expected_total) + tolerance = expected_total * 0.15 # 15% tolerance + + if weight_diff > tolerance: + self.show_error(f"Total weight doesn't match! Expected ~{expected_total:.1f} kg, got {total_weight:.1f}") + return + + # Data looks good + self.unlock_screen() + + except ValueError: + self.show_error("Please enter valid data in correct format") + + def update_submit_timer(self): + """Update countdown timer and check if submit can be enabled""" + # Check if widgets still exist (user might have clicked back) + try: + if self.submit_unlock_time > 0: + self.timer_label.config(text=f"Submit available in {self.submit_unlock_time} seconds...") + self.submit_unlock_time -= 1 + self.root.after(1000, self.update_submit_timer) + else: + # Timer finished, check if all entries have data + all_filled = all(entry.get().strip() for entry in self.entries_to_check) + + if all_filled: + # Enable submit button + self.submit_btn.config( + text="SUBMIT", + state='normal', + bg='#00aa00', + command=self.submit_command + ) + self.timer_label.config(text="You can now submit!") + else: + # Check again in 1 second + self.timer_label.config(text="Fill all fields to enable submit") + self.root.after(1000, self.check_entries_filled) + except tk.TclError: + # Widgets were destroyed (user clicked back), stop the timer + pass + + def check_entries_filled(self): + """Continuously check if entries are filled after timer expires""" + try: + all_filled = all(entry.get().strip() for entry in self.entries_to_check) + + if all_filled: + self.submit_btn.config( + text="SUBMIT", + state='normal', + bg='#00aa00', + command=self.submit_command + ) + self.timer_label.config(text="You can now submit!") + else: + self.timer_label.config(text="Fill all fields to enable submit") + self.root.after(1000, self.check_entries_filled) + except tk.TclError: + # Widgets were destroyed (user clicked back), stop checking + pass + + def show_error(self, message): + self.clear_container() + + error_label = tk.Label( + self.container, + text="ERROR", + font=('Arial', 48, 'bold'), + fg='#ff4444', + bg='#1a1a1a' + ) + error_label.pack(pady=20) + + msg_label = tk.Label( + self.container, + text=message, + font=('Arial', 24), + fg='white', + bg='#1a1a1a', + wraplength=800 + ) + msg_label.pack(pady=20) + + retry_btn = tk.Button( + self.container, + text="TRY AGAIN", + font=('Arial', 24, 'bold'), + bg='#0066cc', + fg='white', + width=15, + command=self.ask_workout_done, + cursor='hand2' if self.demo_mode else '' + ) + retry_btn.pack(pady=30) + + def unlock_screen(self): + # Save workout data to log + self.save_workout_log() + + self.clear_container() + + success_label = tk.Label( + self.container, + text="Great job! 💪", + font=('Arial', 48, 'bold'), + fg='#00ff00', + bg='#1a1a1a' + ) + success_label.pack(pady=30) + + unlock_label = tk.Label( + self.container, + text="Screen Unlocked!", + font=('Arial', 36), + fg='white', + bg='#1a1a1a' + ) + unlock_label.pack(pady=20) + + self.root.after(1500, self.close) + + def has_logged_today(self): + """Check if workout has been logged today""" + if not os.path.exists(self.log_file): + return False + + try: + with open(self.log_file, 'r') as f: + logs = json.load(f) + + today = datetime.now().strftime('%Y-%m-%d') + return today in logs + except (json.JSONDecodeError, IOError): + return False + + def save_workout_log(self): + """Save workout data to log file""" + # Load existing logs + logs = {} + if os.path.exists(self.log_file): + try: + with open(self.log_file, 'r') as f: + logs = json.load(f) + except (json.JSONDecodeError, IOError): + logs = {} + + # Add today's workout + today = datetime.now().strftime('%Y-%m-%d') + logs[today] = { + 'timestamp': datetime.now().isoformat(), + 'workout_data': self.workout_data + } + + # Save updated logs + try: + with open(self.log_file, 'w') as f: + json.dump(logs, f, indent=2) + except IOError as e: + print(f"Warning: Could not save workout log: {e}") + + def close(self): + self.root.destroy() + sys.exit(0) + + def run(self): + self.root.mainloop() + + +if __name__ == '__main__': + # Check for --production flag + demo_mode = True # Default to demo mode for safety + + if len(sys.argv) > 1 and sys.argv[1] == '--production': + demo_mode = False + + locker = ScreenLocker(demo_mode=demo_mode) + locker.run() diff --git a/PYTHON/screen_locker/workout-locker.service b/PYTHON/screen_locker/workout-locker.service new file mode 100644 index 0000000..f44732e --- /dev/null +++ b/PYTHON/screen_locker/workout-locker.service @@ -0,0 +1,14 @@ +[Unit] +Description=Workout Screen Locker +After=graphical-session.target + +[Service] +Type=simple +Environment=DISPLAY=:0 +ExecStartPre=/bin/sleep 3 +ExecStart=/usr/bin/python3 /home/kuhy/testsAndMisc/PYTHON/screen_locker/screen_lock.py +Restart=no +User=%u + +[Install] +WantedBy=graphical-session.target