Skip to content
This repository was archived by the owner on Mar 8, 2026. It is now read-only.

Commit d9d9e50

Browse files
committed
tray, notification, fix buzzheavier upload, ui fixes
1 parent f10498a commit d9d9e50

6 files changed

Lines changed: 150 additions & 44 deletions

File tree

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ requests
22
pyinstaller
33
pywebview[gtk]; sys_platform == "linux"
44
pywebview; sys_platform != "linux"
5-
# desktop-notifier (NOT USED FOR NOW! will be used in a future update :3)
6-
# pystray (NOT USED FOR NOW! will be used in a future update :3)
5+
desktop-notifier
6+
pystray
77
termcolor

src/back/api/sendingFile.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ def buzzheavier(file_path):
5454
with open(file_path, "rb") as f:
5555
response = requests.put(url, data=f, headers=HEADERS)
5656
if response.status_code in [200, 201]:
57-
return response.text.strip()
57+
data = response.json()
58+
file_id = data.get("data", {}).get("id")
59+
if file_id:
60+
return f"https://buzzheavier.com/{file_id}"
61+
return "Error: Could not find file ID in response."
5862
return f"Server Error: {response.status_code}"
5963
except Exception as e:
6064
return f"Request Failed: {str(e)}"

src/back/system/contact.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from src.back.api.sendingFile import catbox, litterbox, buzzheavier
55
from src.back.api.checkForUpdate import isUpdateAvailable
6+
from src.back.util.notify import notify
67

78
class API:
89
def pickFile(self):
@@ -15,18 +16,30 @@ def pickFile(self):
1516
return None
1617

1718
def uploadTo(self, path, platform, duration="1h"):
19+
filename = os.path.basename(path)
20+
notify("Upload Started", f"Sending {filename} to {platform}...")
21+
22+
result = ""
1823
if platform == "catbox":
19-
return catbox(path)
24+
result = catbox(path)
2025
elif platform == "litterbox":
21-
return litterbox(path, duration)
26+
result = litterbox(path, duration)
2227
elif platform == "buzzheavier":
23-
return buzzheavier(path)
24-
return "Unknown platform"
28+
result = buzzheavier(path)
29+
else:
30+
result = "Unknown platform"
31+
32+
if result.startswith("http"):
33+
notify("Upload Success!", f"Link: {result}")
34+
else:
35+
notify("Upload Failed", f"Problem with {platform}: {result}")
36+
37+
return result
2538

2639
def checkForUpdates(self):
2740
try:
2841
with open("version.txt", "r") as f:
2942
currentVersion = f.read().strip()
3043
return isUpdateAvailable(currentVersion)
3144
except Exception as e:
32-
return f"Error: {str(e)}"
45+
return {"status": "error", "message": str(e)}

src/back/util/notify.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import asyncio
2+
from desktop_notifier import DesktopNotifier
3+
import src.back.util.print as print
4+
from sys import platform
5+
from pathlib import Path
6+
7+
baseDir = Path(__file__).resolve().parent.parent.parent.parent
8+
iconExt = "ico" if platform == "win32" else "png"
9+
iconPath = baseDir / "assets" / "icon" / f"SendYourFiles.{iconExt}"
10+
11+
notifier = DesktopNotifier(
12+
app_name="Send Your Files",
13+
app_icon=iconPath
14+
)
15+
16+
async def _send(title, message):
17+
try:
18+
await notifier.send(title=title, message=message, icon=iconPath)
19+
except Exception as e:
20+
print.error(f"Failed to send notification: {e}")
21+
22+
def notify(title, message):
23+
try:
24+
loop = asyncio.get_event_loop()
25+
if loop.is_running():
26+
loop.create_task(_send(title, message))
27+
else:
28+
loop.run_until_complete(_send(title, message))
29+
except Exception:
30+
asyncio.run(_send(title, message))

src/front/main/index.html

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@
205205
</div>
206206

207207
<div class="frame">
208-
<div class="anotherElem">
208+
<div class="anotherElem logs">
209209
<pre id="logs">No logs yet. Send a file!</pre>
210210
</div>
211211

@@ -214,4 +214,12 @@
214214
<div class="button" onclick="showPopup('platformPopup')">Upload to...</div>
215215
</div>
216216
</div>
217-
</main>
217+
</main>
218+
219+
<style>
220+
.logs {
221+
max-width: 350px;
222+
scrollbar-width: auto;
223+
scrollbar-color: var(--frameColor) var(--elemColor);
224+
}
225+
</style>

src/front/window.py

Lines changed: 85 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,103 @@
11
import webview as wv
22
import os
33
import sys
4+
import threading
5+
import pystray
6+
from PIL import Image
47

58
import src.back.util.print as print
69
from src.back.system.contact import API
710

8-
def startUp(debugMode):
9-
# def loadCSS(window):
10-
# whereCss = os.path.join(os.path.dirname(__file__), "cacaStyle.css")
11-
# with open(whereCss, "r") as f:
12-
# css = f.read()
13-
# window.load_css(css)
11+
class WindowManager:
12+
def __init__(self):
13+
self.window = None
14+
self.debugMode = False
15+
self.projectRoot = self.getProjectRoot()
16+
self.iconPath = self.getIconPath()
1417

15-
API.checkForUpdates(API())
18+
def getProjectRoot(self):
19+
if getattr(sys, "frozen", False):
20+
return sys._MEIPASS
21+
return os.path.dirname(
22+
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
23+
)
1624

17-
here = os.path.join(os.path.dirname(__file__), "main", "index.html")
18-
print.debug(f"URL for HTTP is at {here}")
25+
def getIconPath(self):
26+
iconExt = ".ico" if sys.platform == "win32" else ".png"
27+
return os.path.join(
28+
self.projectRoot, "assets", "icon", f"SendYourFiles{iconExt}"
29+
)
1930

20-
if debugMode:
21-
print.success("Debug mode is enabled. I don't know why you'd want this.")
31+
def createWindow(self):
32+
if self.window:
33+
self.showWindow()
34+
return
2235

23-
# NO idea what this is, probably guessing PyInstaller's OneFile thingy.
24-
if getattr(sys, "frozen", False):
25-
projectRoot = sys._MEIPASS
26-
else:
27-
projectRoot = os.path.dirname(
28-
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
36+
htmlPath = os.path.join(os.path.dirname(__file__), "main", "index.html")
37+
print.debug(f"Creating window with URL: {htmlPath}")
38+
39+
self.window = wv.create_window(
40+
title="Send Your Files",
41+
url=htmlPath,
42+
js_api=API(),
43+
width=800,
44+
height=600,
2945
)
3046

31-
iconExt = ".ico" if sys.platform == "win32" else ".png"
32-
iconPath = os.path.join(projectRoot, "assets", "icon", f"SendYourFiles{iconExt}")
47+
self.window.events.closing += self.onWindowClosing
48+
49+
def onWindowClosing(self):
50+
print.debug("X clicked! Hiding to tray and clearing RAM...")
51+
self.window.load_html(" ") # less ram usage :3 (hopefully)
52+
self.window.hide()
53+
return False
3354

34-
print.debug(f"Using icon at: {iconPath}")
55+
def showWindow(self, icon=None, item=None):
56+
if self.window:
57+
print.debug("Refreshing UI and showing window...")
58+
htmlPath = os.path.join(os.path.dirname(__file__), "main", "index.html")
59+
self.window.load_url(htmlPath)
60+
self.window.show()
61+
else:
62+
self.createWindow()
3563

36-
wv.create_window(
37-
title="Send Your Files",
38-
url=here,
39-
js_api=API(),
64+
def quitApp(self, icon, item):
65+
print.warning("Shutting down application...")
66+
icon.stop()
67+
os._exit(0)
4068

41-
width=800,
42-
height=600,
43-
)
69+
def setupTray(self):
70+
try:
71+
image = Image.open(self.iconPath)
72+
menu = pystray.Menu(
73+
pystray.MenuItem("Open", self.showWindow, default=True),
74+
pystray.MenuItem("Quit", self.quitApp),
75+
)
4476

45-
# window.events.loaded += loadCSS
46-
wv.start(
47-
http_server=True,
48-
private_mode=True,
77+
self.trayIcon = pystray.Icon(
78+
"SendYourFiles", image, "Send Your Files", menu
79+
)
80+
self.trayIcon.run()
81+
except Exception as e:
82+
print.error(f"Failed to setup tray: {e}")
4983

50-
debug=debugMode,
51-
icon=iconPath,
52-
)
84+
def start(self, debugMode):
85+
self.debugMode = debugMode
86+
if self.debugMode:
87+
print.success("Debug mode is active.")
88+
89+
trayThread = threading.Thread(target=self.setupTray, daemon=True)
90+
trayThread.start()
91+
92+
self.createWindow()
93+
wv.start(
94+
http_server=True,
95+
private_mode=True,
96+
debug=self.debugMode,
97+
icon=self.iconPath,
98+
)
99+
100+
101+
def startUp(debugMode):
102+
manager = WindowManager()
103+
manager.start(debugMode)

0 commit comments

Comments
 (0)