bombsquad-plugin-manager/plugins/utilities/fileman.py

1997 lines
67 KiB
Python
Raw Normal View History

2025-08-10 16:01:28 +03:00
# Copyright 2025 - Solely by BrotherBoard
# Intended for personal use only
# Bug? Feedback? Telegram >> @BroBordd
"""
FileMan v1.0 - Advanced file manager
Adds a button to settings menu.
Experimental. Read code to know more.
"""
from babase import (
PluginSubsystem as SUB,
Plugin,
env
)
from bauiv1 import (
get_virtual_screen_size as res,
clipboard_set_text as COPY,
get_string_height as strh,
get_string_width as strw,
get_special_widget as zw,
get_replays_dir as rdir,
containerwidget as cw,
hscrollwidget as hsw,
screenmessage as SM,
buttonwidget as obw,
scrollwidget as sw,
SpecialChar as sc,
imagewidget as iw,
textwidget as tw,
gettexture as gt,
apptimer as teck,
AppTimer as tuck,
getsound as gs,
charstr as cs,
MainWindow,
open_url,
Call,
app
)
from os.path import (
basename,
getmtime,
splitext,
dirname,
getsize,
exists,
isfile,
isdir,
join,
sep
)
from os import (
listdir as ls,
getcwd,
rename,
remove,
access,
mkdir,
X_OK,
R_OK
)
from shutil import (
copytree,
rmtree,
copy,
move
)
from bascenev1 import new_replay_session as REP
from http.client import HTTPSConnection as GO
from datetime import datetime as DT
from mimetypes import guess_type
from random import uniform as UF
from threading import Thread
from pathlib import Path
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
class FileMan(MainWindow):
VER = '1.0'
INS = []
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
@classmethod
def resize(c):
c.clean()
[_.on_resize() for _ in c.INS]
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
@classmethod
def clean(c):
c.INS = [_ for _ in c.INS if not _.gn and _.p.exists()]
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
@classmethod
def loadc(c):
2025-08-10 13:02:22 +00:00
[setattr(c, f'COL{i}', _) for i, _ in enumerate(var('col'))]
2025-08-10 16:01:28 +03:00
def __del__(s):
s.__class__.clean()
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def on_resize(s):
[_.delete() for _ in s.killme]
s.killme.clear()
c = s.uploadc
s.spyt = s.sharel = s.buf = s.uploadc = None
2025-08-10 13:02:22 +00:00
if c:
c.close()
2025-08-10 16:01:28 +03:00
s.fresh()
2025-08-10 13:02:22 +00:00
def __init__(s, src):
2025-08-10 16:01:28 +03:00
s.__class__.clean()
s.__class__.INS.append(s)
s.wop()
s.url = s.urlo = var('cwd')
s.urlbln = s.dro = s.gn = s.rlyd = s.flon = False
2025-08-10 13:02:22 +00:00
s.amoled = sum(s.COL5) == 0
2025-08-10 16:01:28 +03:00
s.pusho = s.sorti = 0
s.pushi = -0.1
2025-08-10 13:02:22 +00:00
s.sl = (None, None)
[setattr(s, _, None) for _ in ['pushe', 'eno', 'leno', 'clp', 'gab',
'clpm', 'rlydt', 'buf', 'uploadc', 'cursnd', 'rfl', 'rflo']]
[setattr(s, _, []) for _ in ['trash', 'btns', 'secs', 'docs', 'drkids', 'drol',
'okes', 'fkids', 'ftrash', 'statkids', 'fcons', 'flkids', 'killme']]
2025-08-10 16:01:28 +03:00
s.pushq = ''
# root
s.p = cw(
background=False,
toolbar_visibility='menu_minimal'
)
s.rect = iw(
texture=gt('softRect'),
2025-08-10 13:02:22 +00:00
opacity=[0.3, 0.85][s.amoled],
2025-08-10 16:01:28 +03:00
color=s.COL5,
parent=s.p
)
super().__init__(
root_widget=s.p,
transition='in_scale',
origin_widget=src
)
s.bg = iw(
texture=gt('white'),
parent=s.p,
2025-08-10 13:02:22 +00:00
position=(-2, 0),
2025-08-10 16:01:28 +03:00
color=s.COL5
)
s.bg2 = bw(
bg='empty',
parent=s.p,
oac=s.bga
)
# dock
s.docs = [iw(
color=s.COL1,
parent=s.p,
texture=gt('white'),
opacity=0.5
) for _ in range(3)]
# sections
s.secs = [tw(
parent=s.p,
text=_,
h_align='center',
color=s.COL4,
scale=0.7
2025-08-10 13:02:22 +00:00
) for _ in ['Action', 'Extra', 'New']]
2025-08-10 16:01:28 +03:00
# actions
s.gab = bw(
parent=s.p,
oac=s.cancel,
2025-08-10 13:02:22 +00:00
size=(0, 0),
2025-08-10 16:01:28 +03:00
selectable=False
)
r = []
for _ in range(6):
2025-08-10 13:02:22 +00:00
l = ['Copy', 'Move', 'Delete', 'Share', 'Rename', 'Open'][_]
2025-08-10 16:01:28 +03:00
r.append(bw(
parent=s.p,
label=l,
2025-08-10 13:02:22 +00:00
oac=Call(s.act, 0, _)
2025-08-10 16:01:28 +03:00
))
s.btns.append(r)
# extra
r = []
for _ in range(4):
2025-08-10 13:02:22 +00:00
l = ['Star', 'Sort', 'Filter', 'Theme'][_]
2025-08-10 16:01:28 +03:00
r.append(bw(
parent=s.p,
label=l,
2025-08-10 13:02:22 +00:00
oac=Call(s.act, 1, _)
2025-08-10 16:01:28 +03:00
))
s.btns.append(r)
s.fltxt = tw(
editable=True,
parent=s.p,
v_align='center',
glow_type='uniform',
allow_clear_button=False
)
s.flh = tw(
parent=s.p,
v_align='center',
color=s.COL0
)
s.gab2 = bw(
parent=s.p,
oac=s.unfl,
2025-08-10 13:02:22 +00:00
size=(0, 0),
2025-08-10 16:01:28 +03:00
selectable=False
)
# new
r = []
for _ in range(2):
2025-08-10 13:02:22 +00:00
l = ['File', 'Folder'][_]
2025-08-10 16:01:28 +03:00
r.append(bw(
parent=s.p,
label=l,
2025-08-10 13:02:22 +00:00
oac=Call(s.act, 2, _)
2025-08-10 16:01:28 +03:00
))
s.btns.append(r)
# back
s.bb = bw(
parent=s.p,
label=' '+cs(sc.BACK),
oac=s.bye
)
2025-08-10 13:02:22 +00:00
cw(s.p, cancel_button=s.bb)
2025-08-10 16:01:28 +03:00
# up
s.ub = bw(
parent=s.p,
label=cs(sc.SHIFT),
oac=s.up
)
# url
s.urlbg = bw(
parent=s.p,
oac=s.urled
)
s.urlt = tw(
color=s.COL2,
text=s.url,
v_align='center',
parent=s.p
)
s.urla = tw(
editable=True,
2025-08-10 13:02:22 +00:00
size=(0, 0),
2025-08-10 16:01:28 +03:00
parent=s.p,
text=s.url
)
2025-08-10 13:02:22 +00:00
s.trash.append(tuck(0.01, s.urlspy, repeat=True))
s.trash.append(tuck(0.1, s.urlbl, repeat=True))
2025-08-10 16:01:28 +03:00
# rf
s.rfb = bw(
parent=s.p,
label=cs(sc.PLAY_BUTTON),
oac=s.rf
)
# pre
s.preb = bw(
parent=s.p,
label=cs(sc.LOGO_FLAT),
oac=s.pre
)
# yes
s.yesbg = iw(
parent=s.p,
texture=gt('white'),
color=s.COL1,
opacity=0.5,
2025-08-10 13:02:22 +00:00
position=(20, 20)
2025-08-10 16:01:28 +03:00
)
s.yesbg2 = iw(
parent=s.p,
texture=gt('white'),
color=s.COL5,
opacity=0.3,
)
s.yesp1 = sw(
parent=s.p,
border_opacity=0,
2025-08-10 13:02:22 +00:00
position=(17, 20)
2025-08-10 16:01:28 +03:00
)
s.yesp2 = cw(
parent=s.yesp1,
background=False
)
s.lmao = tw(
parent=s.yesp2,
text=''
)
# oke
s.okes = [tw(
parent=s.p,
text=_,
h_align='left',
color=s.COL4,
scale=0.7
) for _ in SRT()]
# drop
s.drbg = iw(
texture=gt('white'),
parent=s.p,
opacity=0.7,
color=s.COL5
)
s.drp1 = sw(
border_opacity=0,
parent=s.p
)
s.drp2 = cw(
background=False,
parent=s.drp1
)
# push
s.pushbg2 = iw(
color=s.COL5,
parent=s.p,
opacity=0,
texture=gt('softRect')
)
s.pushbg = iw(
color=s.COL1,
parent=s.p,
opacity=0,
texture=gt('white')
)
s.pusht = tw(
color=s.COL2,
parent=s.p,
h_align='center',
v_align='center'
)
2025-08-10 13:02:22 +00:00
s.trash.append(tuck(0.01, s.fpush, repeat=True))
2025-08-10 16:01:28 +03:00
# finally
s.fresh()
2025-08-10 13:02:22 +00:00
teck(0.5, lambda: s.push(f'FileMan v{s.VER} Ready!', du=1.5) if s.eno is None else 0)
2025-08-10 16:01:28 +03:00
def meh(s):
if s.sl[0] is None:
s.btw('Select something!')
return 1
if s.sl[1] == '..':
s.btw('What are you doing blud')
return 1
2025-08-10 13:02:22 +00:00
def btw(s, t, du=3):
2025-08-10 16:01:28 +03:00
s.snd('block')
2025-08-10 13:02:22 +00:00
s.push(t, color=s.COL3, du=du)
def act(s, i, j, gay=False):
if s.gn:
return
2025-08-10 16:01:28 +03:00
w = s.btns[i][j]
match i:
case 0:
match j:
case 0:
if s.clp:
if s.clpm != j:
s.btw("You're already doing something else!")
return
c = var('cwd')
2025-08-10 13:02:22 +00:00
chk = join(c, basename(s.clp))
st1, st2 = splitext(chk)
2025-08-10 16:01:28 +03:00
nn = st1+'_copy'+st2 if exists(chk) else chk
if exists(nn):
2025-08-10 13:02:22 +00:00
s.btw('A copy of this '+['file', 'folder']
[isdir(chk)]+' already exists!')
2025-08-10 16:01:28 +03:00
return
2025-08-10 13:02:22 +00:00
try:
[copy, copytree][isdir(s.clp)](s.clp, nn)
2025-08-10 16:01:28 +03:00
except Exception as e:
s.btw(str(e))
return
else:
GUN()
s.push('Pasted!')
2025-08-10 13:02:22 +00:00
s.clp = None
2025-08-10 16:01:28 +03:00
s.fresh()
else:
2025-08-10 13:02:22 +00:00
if s.meh():
return
2025-08-10 16:01:28 +03:00
s.clp = s.sl[1]
s.clpm = j
s.push(f'Copied! Now go to destination.')
GUN()
s.fresh(skip=True)
case 1:
if s.clp:
if s.clpm != j:
s.btw("You are already doing something else!")
return
c = var('cwd')
2025-08-10 13:02:22 +00:00
chk = join(c, basename(s.clp))
2025-08-10 16:01:28 +03:00
if exists(chk):
2025-08-10 13:02:22 +00:00
s.btw('There is a '+['file', 'folder']
[isdir(chk)]+' with the same name here.')
2025-08-10 16:01:28 +03:00
return
2025-08-10 13:02:22 +00:00
try:
move(s.clp, c)
2025-08-10 16:01:28 +03:00
except Exception as e:
s.btw(str(e))
return
else:
GUN()
s.push('Pasted!')
s.clp = None
s.fresh()
else:
2025-08-10 13:02:22 +00:00
if s.meh():
return
2025-08-10 16:01:28 +03:00
s.clp = s.sl[1]
s.clpm = j
s.push(f'Now go to destination and paste.')
GUN()
s.fresh(skip=True)
case 2:
if s.clpm:
s.btw("Finish what you're doing first!")
return
2025-08-10 13:02:22 +00:00
if s.meh():
return
2025-08-10 16:01:28 +03:00
h = s.sl[1]
bn = basename(h)
if not s.rlyd:
2025-08-10 13:02:22 +00:00
s.beep(1, 0)
s.push(f"Really delete "+["the file '"+bn+"'", "the whole '"+bn+"' folder"]
[isdir(h)]+" forever? Press again to confirm.", du=3, color=s.COL3)
s.rlydt = tuck(2.9, Call(setattr, s, 'rlyd', False))
2025-08-10 16:01:28 +03:00
s.rlyd = True
return
s.rlyd = False
s.rlydt = None
2025-08-10 13:02:22 +00:00
f = [remove, rmtree][isdir(h)]
try:
f(h)
2025-08-10 16:01:28 +03:00
except Exception as e:
s.btw(str(e))
return
else:
GUN()
s.push('Deleted!')
2025-08-10 13:02:22 +00:00
s.sl = (None, None)
2025-08-10 16:01:28 +03:00
s.fresh()
case 3:
2025-08-10 13:02:22 +00:00
if s.meh():
return
2025-08-10 16:01:28 +03:00
f = s.sl[1]
if isdir(f):
s.btw("You can't share a folder!")
return
s.wop()
o = w.get_screen_space_center()
2025-08-10 13:02:22 +00:00
xs, ys = 400, 170
2025-08-10 16:01:28 +03:00
p = s.uploadp = cw(
parent=zw('overlay_stack'),
scale_origin_stack_offset=o,
stack_offset=o,
2025-08-10 13:02:22 +00:00
size=(xs, ys),
2025-08-10 16:01:28 +03:00
background=False,
transition='in_scale'
)
s.killme.append(p)
iw(
parent=p,
2025-08-10 13:02:22 +00:00
size=(xs*1.2, ys*1.2),
2025-08-10 16:01:28 +03:00
texture=gt('softRect'),
2025-08-10 13:02:22 +00:00
opacity=[0.2, 0.55][s.amoled],
position=(-xs*0.1, -ys*0.1),
2025-08-10 16:01:28 +03:00
color=s.COL5
)
iw(
2025-08-10 13:02:22 +00:00
parent=p,
texture=gt('white'),
color=s.COL1,
opacity=0.7,
size=(xs, ys)
2025-08-10 16:01:28 +03:00
)
bw(
parent=p,
label='Back',
oac=s.cupload,
2025-08-10 13:02:22 +00:00
position=(30, 15),
size=(xs-60, 30)
2025-08-10 16:01:28 +03:00
)
s.cpsharelb = bw(
parent=p,
label='...',
oac=s.cpsharel,
2025-08-10 13:02:22 +00:00
position=(30, 50),
size=(xs-60, 30)
2025-08-10 16:01:28 +03:00
)
s.opsharelb = bw(
parent=p,
label='...',
oac=s.opsharel,
2025-08-10 13:02:22 +00:00
position=(30, 85),
size=(xs-60, 30)
2025-08-10 16:01:28 +03:00
)
bw(
parent=p,
label='Upload to bashupload.com',
oac=s.upload,
2025-08-10 13:02:22 +00:00
position=(30, 120),
size=(xs-60, 30)
2025-08-10 16:01:28 +03:00
)
case 4:
2025-08-10 13:02:22 +00:00
if s.meh():
return
2025-08-10 16:01:28 +03:00
t = s.fkids[s.sl[0]]
fp = s.sl[1]
if s.clp == j:
q = tw(query=t)
try:
2025-08-10 13:02:22 +00:00
if sep in q:
raise ValueError(
"You can't use directory separator in filename!")
2025-08-10 16:01:28 +03:00
Path(q)
except Exception as e:
s.btw(str(e) or 'Invalid filename!')
return
else:
if (basename(fp) == q) and not gay:
s.btw("Write a new name blud")
return
2025-08-10 13:02:22 +00:00
chk = join(var('cwd'), q)
2025-08-10 16:01:28 +03:00
if exists(chk):
2025-08-10 13:02:22 +00:00
s.btw(
f"There is a {['file', 'folder'][isdir(chk)]} with this name already!")
2025-08-10 16:01:28 +03:00
return
else:
2025-08-10 13:02:22 +00:00
nfp = join(dirname(fp), q)
2025-08-10 16:01:28 +03:00
try:
2025-08-10 13:02:22 +00:00
rename(fp, nfp)
2025-08-10 16:01:28 +03:00
except PermissionError:
2025-08-10 13:02:22 +00:00
if exists(nfp):
pass
2025-08-10 16:01:28 +03:00
else:
s.push('Permission denied!')
return
except Exception as e:
s.btw(str(e))
return
else:
s.push('Renamed!')
s.clp = None
GUN()
s.fresh(sl=nfp)
else:
if s.clpm:
s.btw("You didn't paste yet blud")
return
2025-08-10 13:02:22 +00:00
tw(t, editable=True, color=s.COL7)
cw(s.yesp2, visible_child=t)
2025-08-10 16:01:28 +03:00
s.clpm = s.clp = j
s.push('Now edit the filename, then press Done.')
if s.flon and s.rfl:
[_.delete() for _ in s.flkids[s.sl[0]]]
GUN()
s.fresh(skip=True)
case 5:
2025-08-10 13:02:22 +00:00
if s.meh():
return
2025-08-10 16:01:28 +03:00
if s.clpm:
s.btw("Press again when you're free!")
return
h = s.sl[1]
bn = basename(h)
if isdir(h):
s.cd(h)
s.snd('deek')
return
s.stat = 1000
s.wop()
k = s.fkids[s.sl[0]] if gay else w
2025-08-10 13:02:22 +00:00
def gcen(): return ((o := k.get_screen_space_center()),
(o[0]-s.size[0]/5, o[1]) if gay else o)[1]
2025-08-10 16:01:28 +03:00
o = gcen()
2025-08-10 13:02:22 +00:00
xs, ys = [_*0.6 for _ in s.size]
2025-08-10 16:01:28 +03:00
p = cw(
parent=zw('overlay_stack'),
scale_origin_stack_offset=o,
2025-08-10 13:02:22 +00:00
size=(xs, ys),
2025-08-10 16:01:28 +03:00
background=False,
transition='in_scale'
)
s.killme.append(p)
iw(
parent=p,
2025-08-10 13:02:22 +00:00
size=(xs*1.2, ys*1.2),
2025-08-10 16:01:28 +03:00
texture=gt('softRect'),
2025-08-10 13:02:22 +00:00
opacity=[0.3, 0.7][s.amoled],
position=(-xs*0.1, -ys*0.1),
2025-08-10 16:01:28 +03:00
color=s.COL5
)
iw(
2025-08-10 13:02:22 +00:00
parent=p,
texture=gt('white'),
color=s.COL5,
opacity=0.7,
size=(xs, ys)
2025-08-10 16:01:28 +03:00
)
b = bw(
parent=p,
2025-08-10 13:02:22 +00:00
position=(20, ys-70),
2025-08-10 16:01:28 +03:00
label=' '+cs(sc.BACK),
2025-08-10 13:02:22 +00:00
size=(50, 50),
oac=Call(s.statbye, p, gcen)
2025-08-10 16:01:28 +03:00
)
2025-08-10 13:02:22 +00:00
cw(p, cancel_button=b)
2025-08-10 16:01:28 +03:00
ix = xs-250
iw(
parent=p,
texture=gt('white'),
color=s.COL1,
2025-08-10 13:02:22 +00:00
position=(90, ys-72),
size=(ix, 54),
2025-08-10 16:01:28 +03:00
opacity=0.5
)
tw(
parent=p,
h_align='center',
v_align='center',
2025-08-10 13:02:22 +00:00
position=(xs/2-60, ys-60),
2025-08-10 16:01:28 +03:00
text=basename(h),
maxwidth=ix-100
)
iw(
parent=p,
texture=gt('white'),
color=s.COL1,
opacity=0.5,
2025-08-10 13:02:22 +00:00
position=(20, 20),
size=(xs-40, ys-110)
2025-08-10 16:01:28 +03:00
)
bw(
parent=p,
label=cs(sc.REWIND_BUTTON),
2025-08-10 13:02:22 +00:00
position=(xs-141, ys-70),
size=(50, 50),
oac=Call(s.stata, -1),
2025-08-10 16:01:28 +03:00
repeat=True
)
bw(
parent=p,
label=cs(sc.FAST_FORWARD_BUTTON),
2025-08-10 13:02:22 +00:00
position=(xs-71, ys-70),
size=(50, 50),
oac=Call(s.stata, 1),
2025-08-10 16:01:28 +03:00
repeat=True
)
s.oops = 0
try:
2025-08-10 13:02:22 +00:00
with open(h, 'r') as f:
2025-08-10 16:01:28 +03:00
da = f.read()
except Exception as ex:
da = ''
s.oops = 1
2025-08-10 13:02:22 +00:00
if isinstance(ex, PermissionError):
kek = 'Permission denied!'
elif isinstance(ex, UnicodeDecodeError):
kek = 'No preview avaiable'
else:
kek = str(ex)
2025-08-10 16:01:28 +03:00
else:
if not da:
s.oops = 1
kek = 'No data'
if not s.oops:
fxs = xs-40
fys = ys-110
2025-08-10 13:02:22 +00:00
s.statsz = (fxs, fys)
2025-08-10 16:01:28 +03:00
p0 = s.statp0 = sw(
parent=p,
2025-08-10 13:02:22 +00:00
position=(20, 20),
size=(fxs, fys),
2025-08-10 16:01:28 +03:00
border_opacity=0,
capture_arrows=True
)
s.statda = da
s.statp = 0
s.statl = []
s.itw()
else:
ty = s.gtype(h)
if ty == 'Replay':
tw(
parent=p,
2025-08-10 13:02:22 +00:00
position=(xs/2-20, ys-150),
2025-08-10 16:01:28 +03:00
text='Press start to preview replay.\nKeep in mind that this will destroy the current FileMan session.',
h_align='center',
color=s.COL4,
maxwidth=xs-60
)
bw(
parent=p,
label='Start',
2025-08-10 13:02:22 +00:00
oac=lambda: (b.activate(), teck(0.1, s.bye),
teck(0.3, Call(REP, h))),
position=(xs/2-75, ys/2-135),
size=(150, 40)
2025-08-10 16:01:28 +03:00
)
elif ty == 'Texture' and bn in TEX():
2025-08-10 13:02:22 +00:00
wd = min(xs-80, ys-150)
2025-08-10 16:01:28 +03:00
tex = gt(splitext(bn)[0])
iw(
parent=p,
texture=tex,
2025-08-10 13:02:22 +00:00
size=(wd, wd),
position=(xs/2-wd/2, 40)
2025-08-10 16:01:28 +03:00
)
elif ty == 'Audio' and bn in AUDIO():
tw(
parent=p,
2025-08-10 13:02:22 +00:00
position=(xs/2-20, ys-150),
2025-08-10 16:01:28 +03:00
text=f'Sound is recognized by filename, not data.\nPress the buttons below to play/pause',
h_align='center',
color=s.COL4,
maxwidth=xs-60
)
bw(
parent=p,
label=cs(sc.PLAY_BUTTON),
2025-08-10 13:02:22 +00:00
oac=lambda: (getattr(s.cursnd, 'stop', lambda: 0)(), setattr(
s, 'cursnd', gs(splitext(bn)[0])), s.cursnd.play()),
position=(xs/2-30, ys/2-135),
size=(40, 40)
2025-08-10 16:01:28 +03:00
)
bw(
parent=p,
label=cs(sc.PAUSE_BUTTON),
2025-08-10 13:02:22 +00:00
oac=lambda: getattr(s.cursnd, 'stop', lambda: 0)(),
position=(xs/2+30, ys/2-135),
size=(40, 40)
2025-08-10 16:01:28 +03:00
)
else:
tw(
parent=p,
text=kek,
2025-08-10 13:02:22 +00:00
position=(xs/2-25, ys/2-35),
2025-08-10 16:01:28 +03:00
h_align='center',
v_align='center',
maxwidth=xs-100
)
case 1:
match j:
case 0:
star = var('star')
c = var('cwd')
if c in star:
star.remove(c)
s.push('Unstarred!')
else:
star.append(c)
s.push('Starred! (bomb top right)')
2025-08-10 13:02:22 +00:00
var('star', star)
2025-08-10 16:01:28 +03:00
GUN()
s.fresh(skip=True)
case 1:
2025-08-10 13:02:22 +00:00
xs, ys = 200, 230
2025-08-10 16:01:28 +03:00
s.wop()
2025-08-10 13:02:22 +00:00
def gcen(): return ((o := w.get_screen_space_center()),
(o[0]-s.size[0]/5, o[1]) if gay else o)[1]
2025-08-10 16:01:28 +03:00
o = gcen()
p = cw(
parent=zw('overlay_stack'),
scale_origin_stack_offset=o,
2025-08-10 13:02:22 +00:00
size=(xs, ys),
2025-08-10 16:01:28 +03:00
background=False,
transition='in_scale',
2025-08-10 13:02:22 +00:00
stack_offset=(o[0], o[1]),
on_outside_click_call=lambda: (cw(p, transition='out_scale'), s.laz())
2025-08-10 16:01:28 +03:00
)
s.killme.append(p)
iw(
parent=p,
2025-08-10 13:02:22 +00:00
size=(xs*1.2, ys*1.2),
2025-08-10 16:01:28 +03:00
texture=gt('softRect'),
2025-08-10 13:02:22 +00:00
opacity=[0.3, 0.7][s.amoled],
position=(-xs*0.1, -ys*0.1),
2025-08-10 16:01:28 +03:00
color=s.COL5
)
iw(
2025-08-10 13:02:22 +00:00
parent=p,
texture=gt('white'),
color=s.COL5,
opacity=0.7,
size=(xs, ys)
2025-08-10 16:01:28 +03:00
)
by = 40
srt = SRT()
for _ in range(4):
bw(
2025-08-10 13:02:22 +00:00
position=(20, ys-20-by-(by+10)*_),
size=(xs-40, by),
2025-08-10 16:01:28 +03:00
label=srt[_],
2025-08-10 13:02:22 +00:00
oac=Call(s.surt, _, p),
2025-08-10 16:01:28 +03:00
parent=p
)
case 2:
s.flon = True
s.snd('deek')
s.fresh(skip=True)
case 3:
ox, oy = s.size
xs = ys = min(ox / 2, oy / 2)
xs *= 1.3
s.wop()
2025-08-10 13:02:22 +00:00
s.push(
'FileMan uses 12 main colors. Tap on a color to edit it. Press outside to cancel.', du=6)
2025-08-10 16:01:28 +03:00
o = w.get_screen_space_center()
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def nuke():
2025-08-10 13:02:22 +00:00
cw(p, transition='out_scale')
2025-08-10 16:01:28 +03:00
s.laz()
s.push('Cancelled! Nothing was saved')
2025-08-10 13:02:22 +00:00
p = cw(parent=zw('overlay_stack'), scale_origin_stack_offset=o, size=(
xs, ys), stack_offset=(-100, 0), background=False, transition='in_scale', on_outside_click_call=nuke)
bw(parent=p, size=(xs+200, ys), bg='empty')
2025-08-10 16:01:28 +03:00
s.killme.append(p)
2025-08-10 13:02:22 +00:00
iw(parent=p, size=(xs * 1.2, ys * 1.2), texture=gt('softRect'),
opacity=[0.3, 0.7][s.amoled], position=(-xs * 0.1, -ys * 0.1), color=s.COL5)
iw(parent=p, texture=gt('white'), color=s.COL5,
opacity=0.7, size=(xs + 200, ys))
temp_colors, scl, sl = [getattr(s, f'COL{i}') for i in range(12)], [
0, 0, 0, 0], 0
2025-08-10 16:01:28 +03:00
kids, nubs, grad = [], [], []
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def save():
if var('col') == temp_colors:
s.btw('At least change a color blud')
return
2025-08-10 13:02:22 +00:00
var('col', temp_colors)
2025-08-10 16:01:28 +03:00
GUN()
2025-08-10 13:02:22 +00:00
cw(p, transition='out_scale')
2025-08-10 16:01:28 +03:00
s.__class__.loadc()
s.bye()
SM('Reopen FileMan to see changes!')
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def update_previews():
f3()
f4()
c = temp_colors[sl]
obw(kids[sl], color=c, textcolor=INV(c))
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def f3():
2025-08-10 13:02:22 +00:00
[iw(l, position=(xs + scl[k] * ps - 16, 39 + qs * 5 - (qs) * k))
for k, l in enumerate(nubs)]
2025-08-10 16:01:28 +03:00
def f4():
c = temp_colors[sl]
2025-08-10 13:02:22 +00:00
[obw(l, color=(c[0] * (k / 19), c[1] * (k / 19), c[2] * (k / 19)))
for k, l in enumerate(grad)]
2025-08-10 16:01:28 +03:00
def f2(k, l):
nonlocal scl
scl[k] = l
val = l / 19.0
if k < 3:
c_list = list(temp_colors[sl])
c_list[k] = val
temp_colors[sl] = new_color = tuple(c_list)
scl[3] = int(max(new_color) * 19)
elif k == 3:
c = temp_colors[sl]
current_max = max(c)
if current_max > 0:
scale = val / current_max
2025-08-10 13:02:22 +00:00
temp_colors[sl] = new_color = (
c[0] * scale, c[1] * scale, c[2] * scale)
2025-08-10 16:01:28 +03:00
scl[:3] = [int(x * 19) for x in new_color]
update_previews()
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def f(z, sh=0):
nonlocal sl, scl
[obw(_, label='') for _ in kids]
obw(kids[z], label=cs(sc.DPAD_CENTER_BUTTON))
sl = z
2025-08-10 13:02:22 +00:00
if not sh:
s.snd('deek')
2025-08-10 16:01:28 +03:00
c = temp_colors[sl]
scl[:3] = [int(x * 19) for x in c]
scl[3] = int(max(c) * 19) if any(c) else 0
update_previews()
bs, qs, ps = (ys - 60) / 3, (ys - 60) / 6, 9
for k in range(4):
for l in range(20):
ah = l / 19.0
b = obw(
parent=p, position=(xs + l * ps, 47 + qs * 5 - qs * k), size=(ps + 2, qs / 2), label='', texture=gt('white'), enable_sound=False, on_activate_call=Call(f2, k, l),
2025-08-10 13:02:22 +00:00
color=((ah, 0, 0) if k < 1 else (0, ah, 0) if k <
2 else (0, 0, ah) if k < 3 else (ah, ah, ah))
2025-08-10 16:01:28 +03:00
)
2025-08-10 13:02:22 +00:00
if k == 3:
grad.append(b)
nubs = [iw(parent=p, size=(35, 35), texture=gt('nub'),
color=(10, 10, 10), opacity=0.4) for _ in range(4)]
2025-08-10 16:01:28 +03:00
for x in range(4):
for y in range(3):
z = x * 3 + y
c = temp_colors[z]
2025-08-10 13:02:22 +00:00
kids.append(bw(parent=p, position=(
20 + (bs + 10) * x, 20 + (bs + 10) * y), size=(bs, bs), color=c, textcolor=INV(c), oac=Call(f, z)))
bw(parent=p, position=(xs + 5, 24 + qs),
size=(172, qs - 2), label='Save', oac=save)
2025-08-10 16:01:28 +03:00
def reset():
mem = COL()
if mem == temp_colors:
s.btw("Reset what? It's already at default")
return
2025-08-10 13:02:22 +00:00
for i, m in enumerate(mem):
2025-08-10 16:01:28 +03:00
temp_colors[i] = m
update_previews()
GUN()
s.push('Restored default colors! now press save')
2025-08-10 13:02:22 +00:00
bw(parent=p, position=(xs + 5, 18.5),
size=(172, qs - 3), label='Reset', oac=reset)
2025-08-10 16:01:28 +03:00
f(0, sh=1)
case 2:
match j:
case 0:
if s.clpm:
s.btw("You're already in the middle of something")
return
c = var('cwd')
2025-08-10 13:02:22 +00:00
n = join(c, 'new_file')
while exists(n):
n += '_again'
try:
Path(n).touch()
2025-08-10 16:01:28 +03:00
except PermissionError:
s.btw('Permission denied!')
return
except Exception as ex:
s.btw(str(ex))
return
s.fresh(sl=n)
# rename
2025-08-10 13:02:22 +00:00
s.act(0, 4, gay=True)
2025-08-10 16:01:28 +03:00
case 1:
if s.clpm:
s.btw("You're already in the middle of something")
return
c = var('cwd')
2025-08-10 13:02:22 +00:00
n = join(c, 'new_folder')
while exists(n):
n += '_again'
try:
mkdir(n)
2025-08-10 16:01:28 +03:00
except PermissionError:
s.btw('Permission denied!')
return
except Exception as ex:
s.btw(str(ex))
return
s.fresh(sl=n)
# rename
2025-08-10 13:02:22 +00:00
s.act(0, 4)
def surt(s, _, p):
2025-08-10 16:01:28 +03:00
if _ == s.sorti:
s.btw('Already sorted by '+SRT()[_]+'!')
return
s.sorti = _
GUN()
2025-08-10 13:02:22 +00:00
cw(p, transition='out_scale')
2025-08-10 16:01:28 +03:00
s.fresh(sl=s.sl[1])
2025-08-10 13:02:22 +00:00
def statbye(s, p, gcen):
try:
cen = gcen()
except:
p.delete()
else:
cw(p, transition='out_scale', scale_origin_stack_offset=cen)
2025-08-10 16:01:28 +03:00
s.laz()
s.statda = None
s.statl = []
s.statp = 0
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def itw(s):
PYTHON_KEYWORDS = {
'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def',
'del', 'elif', 'else', 'except', 'False', 'finally', 'for', 'from',
'global', 'if', 'import', 'in', 'is', 'lambda', 'None', 'nonlocal',
'not', 'or', 'pass', 'raise', 'return', 'True', 'try', 'while', 'with', 'yield'
}
PYTHON_BUILTINS = {
'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
'chr', 'classmethod', 'compile', 'complex', 'delattr', 'dict', 'dir', 'divmod',
'enumerate', 'eval', 'exec', 'filter', 'float', 'format', 'frozenset', 'getattr',
'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance',
'issubclass', 'iter', 'len', 'list', 'locals', 'map', 'max', 'memoryview',
'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted',
'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip'
}
OPERATORS = {'+', '-', '*', '/', '%', '=', '!', '<', '>', '&', '|', '^', '~'}
BRACKETS = {'(', ')', '{', '}', '[', ']', ':', ',', '.'}
s.COL_KEYWORD = getattr(s, 'COL_KEYWORD', (1.5, 0.9, 0.4))
s.COL_BUILTIN = getattr(s, 'COL_BUILTIN', (0.7, 1.2, 1.8))
s.COL_STRING = getattr(s, 'COL_STRING', (0.5, 1.5, 0.5))
s.COL_NUMBER = getattr(s, 'COL_NUMBER', (1.2, 1.2, 0.5))
s.COL_OPERATOR = getattr(s, 'COL_OPERATOR', (1.5, 1.5, 1.5))
s.COL_BRACKET = getattr(s, 'COL_BRACKET', (0.9, 0.9, 0.9))
2025-08-10 13:02:22 +00:00
s.COL_END_MARKER = getattr(s, 'COL_END_MARKER', (1.8, 0.6, 0.6)) # Neon Red for the marker
2025-08-10 16:01:28 +03:00
da = s.statda
end_marker = f'[End of chunk | Press {cs(sc.FAST_FORWARD_BUTTON)}]'
if len(da) > s.stat:
if len(da) > s.statp + int(s.stat / 2):
da = da[s.statp:s.stat + s.statp] + end_marker
else:
da = da[s.statp:s.stat + s.statp]
az = sum(s.statl)
2025-08-10 13:02:22 +00:00
lines = [_.replace('\\n', '\\'+"~"+"n") for _ in da.splitlines()]
2025-08-10 16:01:28 +03:00
zc = len(str(az + len(lines)))
da = '\\n'.join([f"{str(i+1+az).zfill(zc)} | {_}" for i, _ in enumerate(lines)])
z = len(da)
p0 = s.statp0
fxs, fys = s.statsz
[_.delete() for _ in s.statkids]
s.statkids.clear()
hh = 35
m = max(da.replace('\\n', '') or ' ', key=GSW)
l = GSW(str(m)) / 1.5
2025-08-10 13:02:22 +00:00
l = max(15, l)
l = min(l, 20)
2025-08-10 16:01:28 +03:00
das = da.split('\\n')
mm = len(max(das, key=len) or '')
ldas = len(das)
s.statl.append(ldas)
rxs = max(l * mm + 30, fxs)
rys = max(hh * ldas, fys - 15)
pos = (0, rys - 40)
po = list(pos)
q0 = cw(parent=p0, size=(fxs, rys), background=False)
p1 = hsw(parent=q0, size=(fxs, rys), border_opacity=0)
q1 = cw(parent=p1, background=False, size=(rxs, fys))
s.statkids += [q0, p1, q1]
# --- Main Rendering Loop ---
i = 0
nc = 0
in_triple_comment = False
triple_quote_char = None
2025-08-10 13:02:22 +00:00
is_first_char_offset_applied = False # Flag for the critical offset
2025-08-10 16:01:28 +03:00
off = zc + 3
try:
mud = int(da[off] == '#')
except IndexError:
mud = 0
while i < z:
# -- Priority 1: The End Marker --
if not in_triple_comment and not mud and da.startswith(end_marker, i):
if not is_first_char_offset_applied:
2025-08-10 13:02:22 +00:00
po[0] -= l * 1.5
is_first_char_offset_applied = True
2025-08-10 16:01:28 +03:00
for c in end_marker:
big = nc < zc
po[0] += l
2025-08-10 13:02:22 +00:00
s.statkids.append(tw(text=c, position=(
po[0], po[1] - (3 if big else 0)), h_align='center', v_align='top', parent=q1, big=big, color=s.COL_END_MARKER))
2025-08-10 16:01:28 +03:00
nc += 1
i += len(end_marker)
continue
# -- Priority 2: Multi-line comment delimiters --
if i + 2 < z and da[i:i+3] in ('"'*3, "'"*3):
chunk = da[i:i+3]
if not in_triple_comment or chunk == triple_quote_char * 3:
if not is_first_char_offset_applied:
2025-08-10 13:02:22 +00:00
po[0] -= l * 1.5
is_first_char_offset_applied = True
2025-08-10 16:01:28 +03:00
if not in_triple_comment:
2025-08-10 13:02:22 +00:00
in_triple_comment = True
triple_quote_char = chunk[0]
2025-08-10 16:01:28 +03:00
else:
2025-08-10 13:02:22 +00:00
in_triple_comment = False
triple_quote_char = None
2025-08-10 16:01:28 +03:00
for _ in range(3):
2025-08-10 13:02:22 +00:00
big = nc < zc
po[0] += l
s.statkids.append(tw(text=da[i], position=(
po[0], po[1] - (3 if big else 0)), h_align='center', v_align='top', parent=q1, big=big, color=s.COL3 if big else s.COL0))
nc += 1
i += 1
2025-08-10 16:01:28 +03:00
continue
# -- Priority 3: Newlines --
if i + 1 < z and da[i:i+2] == '\\n':
2025-08-10 13:02:22 +00:00
po[0] = pos[0]-l*1.5
po[1] -= hh
nc = 0
2025-08-10 16:01:28 +03:00
try:
mud = int(da[i + 2 + off] == '#' and not in_triple_comment)
except IndexError:
mud = 0
i += 2
continue
# -- Priority 4: Render based on state (comment or code) --
# Apply the critical offset before rendering the first character
if not is_first_char_offset_applied:
2025-08-10 13:02:22 +00:00
po[0] -= l * 1.5
is_first_char_offset_applied = True
2025-08-10 16:01:28 +03:00
if in_triple_comment or mud:
big = nc < zc
2025-08-10 13:02:22 +00:00
color = (s.COL0 if big else s.COL3) if in_triple_comment else (
s.COL10 if big else s.COL11)
2025-08-10 16:01:28 +03:00
po[0] += l
2025-08-10 13:02:22 +00:00
s.statkids.append(tw(text=da[i], position=(
po[0], po[1] - (3 if big else 0)), h_align='center', v_align='top', parent=q1, big=big, color=color))
nc += 1
i += 1
2025-08-10 16:01:28 +03:00
continue
# -- Priority 5: Python Syntax Highlighting --
2025-08-10 13:02:22 +00:00
char = da[i]
token = char
token_color = s.COL2
2025-08-10 16:01:28 +03:00
if char in ("'", '"'):
k = i + 1
2025-08-10 13:02:22 +00:00
while k < z and (da[k] != char or da[k-1] == '\\'):
k += 1
token = da[i:k+1]
token_color = s.COL_STRING
2025-08-10 16:01:28 +03:00
elif char.isdigit() or (char == '.' and i + 1 < z and da[i+1].isdigit()):
k = i
2025-08-10 13:02:22 +00:00
while k < z and (da[k].isdigit() or da[k] == '.'):
k += 1
token = da[i:k]
token_color = s.COL_NUMBER
2025-08-10 16:01:28 +03:00
elif char.isalpha() or char == '_':
k = i
2025-08-10 13:02:22 +00:00
while k < z and (da[k].isalnum() or da[k] == '_'):
k += 1
2025-08-10 16:01:28 +03:00
token = da[i:k]
2025-08-10 13:02:22 +00:00
if token in PYTHON_KEYWORDS:
token_color = s.COL_KEYWORD
elif token in PYTHON_BUILTINS:
token_color = s.COL_BUILTIN
elif char in OPERATORS:
token_color = s.COL_OPERATOR
elif char in BRACKETS:
token_color = s.COL_BRACKET
2025-08-10 16:01:28 +03:00
for c in token:
2025-08-10 13:02:22 +00:00
big = nc < zc
po[0] += l
s.statkids.append(tw(text=c, position=(
po[0], po[1] - (3 if big else 0)), h_align='center', v_align='top', parent=q1, big=big, color=token_color))
2025-08-10 16:01:28 +03:00
nc += 1
i += len(token)
2025-08-10 13:02:22 +00:00
cw(q0, visible_child=tw(parent=q0, text='', position=(0, rys)))
cw(q1, visible_child=tw(parent=q1, text='', position=(0, rys)))
def stata(s, i):
2025-08-10 16:01:28 +03:00
if not s.oops:
n = s.statp + s.stat*i
ok = len(s.statda)
if ok <= n:
2025-08-10 13:02:22 +00:00
s.btw('Reached EOF!', du=1)
2025-08-10 16:01:28 +03:00
return
if n < 0:
2025-08-10 13:02:22 +00:00
s.btw('Already at first chunk!', du=1)
2025-08-10 16:01:28 +03:00
return
s.snd('deek')
s.statp = n
2025-08-10 13:02:22 +00:00
if i < 0:
[s.statl.pop(-1) for _ in [0, 0]]
2025-08-10 16:01:28 +03:00
s.itw()
else:
s.btw('No more open file buffers!')
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def cpsharel(s):
l = s.vsharel()
2025-08-10 13:02:22 +00:00
if not l:
return
2025-08-10 16:01:28 +03:00
COPY(str(l))
2025-08-10 13:02:22 +00:00
s.ding(1, 1)
2025-08-10 16:01:28 +03:00
s.push(f"Copied '{l}' to clipboard!")
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def opsharel(s):
l = s.vsharel()
2025-08-10 13:02:22 +00:00
if not l:
return
2025-08-10 16:01:28 +03:00
s.snd('deek')
open_url(l)
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def vsharel(s):
2025-08-10 13:02:22 +00:00
l = getattr(s, 'sharel', 0)
2025-08-10 16:01:28 +03:00
if not l:
s.btw("Upload first!")
return
return l
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def cupload(s):
c = s.uploadc
s.spyt = s.sharel = s.buf = s.uploadc = None
if c:
c.close()
2025-08-10 13:02:22 +00:00
s.ding(0, 0)
2025-08-10 16:01:28 +03:00
s.push('Cancelled!')
2025-08-10 13:02:22 +00:00
else:
s.laz()
cw(s.uploadp, transition='out_scale')
2025-08-10 16:01:28 +03:00
def upload(s):
f = s.sl[1]
2025-08-10 13:02:22 +00:00
s.ding(1, 0)
2025-08-10 16:01:28 +03:00
s.push('Uploading...')
2025-08-10 13:02:22 +00:00
Thread(target=Call(s._upload, f)).start()
s.spyt = tuck(0.2, Call(s.spy, s.on_upload), repeat=True)
2025-08-10 16:01:28 +03:00
def _upload(s, l):
try:
c = s.uploadc = GO('bashupload.com')
filename = basename(l)
url_path = '/' + filename
2025-08-10 13:02:22 +00:00
with open(l, 'rb') as f:
body = f.read()
2025-08-10 16:01:28 +03:00
headers = {'Content-Type': 'application/octet-stream'}
c.request('POST', url_path, body=body, headers=headers)
s.buf = c.getresponse().read().decode()
except Exception:
2025-08-10 13:02:22 +00:00
if s.uploadc:
s.buf = ''
2025-08-10 16:01:28 +03:00
finally:
if s.uploadc:
s.uploadc.close()
s.uploadc = s.sharel = None
2025-08-10 13:02:22 +00:00
def on_upload(s, t):
2025-08-10 16:01:28 +03:00
if not t:
s.btw("Couldn't upload")
return
s.sharel = t.splitlines()[5][5:]+'?download=1'
2025-08-10 13:02:22 +00:00
s.ding(0, 1)
2025-08-10 16:01:28 +03:00
s.push('Success!')
2025-08-10 13:02:22 +00:00
obw(s.cpsharelb, label='Copy Direct URL')
obw(s.opsharelb, label=s.sharel)
def ding(s, i, j):
a = ['Small', '']
x, y = a[i], a[j]
2025-08-10 16:01:28 +03:00
s.snd('ding'+x)
2025-08-10 13:02:22 +00:00
teck(0.1, gs('ding'+y).play)
def beep(s, i, j):
2025-08-10 16:01:28 +03:00
s.snd(f'raceBeep{str(i+1)}')
2025-08-10 13:02:22 +00:00
teck(0.1, gs(f'raceBeep{str(j+1)}').play)
def spy(s, f):
if s.buf is None:
return
2025-08-10 16:01:28 +03:00
b = s.buf
s.buf = None
f(b)
s.spyt = None
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def cancel(s):
c = s.clp
s.clp = None
s.push('Cancelled!')
s.snd('deek')
2025-08-10 13:02:22 +00:00
s.fresh(skip=c != 4)
def fresh(s, skip=False, sl=None):
if s.gn:
return
rx, ry = res()
z = s.size = (rx*0.8, ry*0.8)
x, y = z
2025-08-10 16:01:28 +03:00
# root
2025-08-10 13:02:22 +00:00
cw(s.p, size=z)
iw(s.bg, size=z)
obw(s.bg2, size=z)
iw(s.rect, size=(x*1.2, y*1.2), position=(-x*0.1, -y*0.1))
2025-08-10 16:01:28 +03:00
# docks, secs, btns
h = (x-80)
f = y-191
v = 18
for i in range(3):
2025-08-10 13:02:22 +00:00
e = h/[2, 3, 6][i]
iw(s.docs[i], size=(e, 100), position=(v, f))
tw(s.secs[i], position=(v+e/2-23, f+1))
a = s.btns[i]
l = int(len(a)/2)
bh = (e-[6, 5, 4][i]*10-(l-1)*10)/l
2025-08-10 16:01:28 +03:00
for j in range(l):
2025-08-10 13:02:22 +00:00
for k in [0, l]:
2025-08-10 16:01:28 +03:00
zz = bh
of = 20
ga = (
(i == k == 0 and s.clpm == j)
or
(i == 0 and j == 1 and k == 3 and s.clpm == 4)
)
if ga and s.clp:
zz -= 40
of -= 2
2025-08-10 13:02:22 +00:00
po = v+of+(bh+20)*j, f+60-30*bool(k)
2025-08-10 16:01:28 +03:00
ww = a[j+k]
2025-08-10 13:02:22 +00:00
obw(ww, position=po, size=(zz, 25))
2025-08-10 16:01:28 +03:00
if not ga:
if i == 1 and j == k == 0:
2025-08-10 13:02:22 +00:00
obw(ww, label=['Star', 'Unstar'][var('cwd') in var('star')])
2025-08-10 16:01:28 +03:00
elif i == 1 and j == 0 and k:
2025-08-10 13:02:22 +00:00
tw(s.fltxt, position=(po[0]-2, po[1]-2))
tw(s.flh, position=(po[0], po[1]-2), max_height=37, maxwidth=zz-42)
obw(s.gab2, position=(po[0]+zz-32, po[1]))
2025-08-10 16:01:28 +03:00
if s.flon:
2025-08-10 13:02:22 +00:00
obw(ww, size=(0, 0), label='')
tw(s.fltxt, size=(zz-38, 27))
tw(s.flh, text='' if s.rfl else 'Write something...')
obw(s.gab2, size=(bh-(zz-38), 25), label='X')
2025-08-10 16:01:28 +03:00
if not s.fltk:
s.rflo = s.fltk = ''
2025-08-10 13:02:22 +00:00
s.fltk = tuck(0.1, s.onfl, repeat=True)
2025-08-10 16:01:28 +03:00
else:
2025-08-10 13:02:22 +00:00
obw(ww, size=(zz, 25), label='Filter')
tw(s.fltxt, size=(0, 0), text='')
tw(s.flh, text='')
obw(s.gab2, size=(0, 0), label='')
2025-08-10 16:01:28 +03:00
s.rfl = s.rflo = s.fltk = None
continue
he = bool(s.clp)
2025-08-10 13:02:22 +00:00
obw(s.gab, position=(po[0]+zz+11, po[1]),
size=(bh-3-zz, 25), label=['', 'X'][he], selectable=he)
obw(ww, label=[['Copy', 'Move', 0, 0, 'Rename']
[s.clpm], ['Paste', 'Done'][s.clpm == 4]][he])
if not he:
s.clpm = None
2025-08-10 16:01:28 +03:00
v += e+20
# back
f = y-70
2025-08-10 13:02:22 +00:00
obw(s.bb, position=(20, f), size=(50, 50))
2025-08-10 16:01:28 +03:00
# up
2025-08-10 13:02:22 +00:00
obw(s.ub, position=(90, f), size=(50, 50))
2025-08-10 16:01:28 +03:00
# url
e = x - 398
2025-08-10 13:02:22 +00:00
obw(s.urlbg, size=(e, 50), position=(195, f))
tw(s.urlt, position=(180, y-60), maxwidth=x-370)
2025-08-10 16:01:28 +03:00
# rf
2025-08-10 13:02:22 +00:00
obw(s.rfb, position=(251+e, f), size=(50, 50))
2025-08-10 16:01:28 +03:00
# pre
2025-08-10 13:02:22 +00:00
obw(s.preb, position=(323+e, f), size=(50, 50))
2025-08-10 16:01:28 +03:00
# skip the rest
2025-08-10 13:02:22 +00:00
if skip:
return
2025-08-10 16:01:28 +03:00
# drop
s.droc()
# oke
fly = 35
2025-08-10 13:02:22 +00:00
sx, sy = x-37, y-230
2025-08-10 16:01:28 +03:00
h = sx/6
v = 30
2025-08-10 13:02:22 +00:00
rat = [3, 1, 1, 1]
for i, _ in enumerate(s.okes):
2025-08-10 16:01:28 +03:00
j = rat[i]
2025-08-10 13:02:22 +00:00
tw(_, position=(v+[30, 0][i != 0], sy-15))
2025-08-10 16:01:28 +03:00
v += h*j
# push
s.rpush()
# files
p = s.yesp2
[_.delete() for _ in s.fkids]
s.fkids.clear()
[_.delete() for _ in s.ftrash]
s.ftrash.clear()
[_.delete() for _ in s.fcons]
s.fcons.clear()
[[i.delete() for i in j] for j in s.flkids]
s.flkids.clear()
fl = s.gfull()
u = s.rfl
if s.flon and s.rfl:
fl = [_ for _ in fl if (_ == '..') or (u in basename(_))]
cur = s.sl[1]
if cur:
2025-08-10 13:02:22 +00:00
if cur in fl:
sl = cur
else:
s.sl = (None, None)
2025-08-10 16:01:28 +03:00
# yes
rsy = len(fl)*fly
2025-08-10 13:02:22 +00:00
sw(s.yesp1, size=(sx, sy-40))
cw(s.yesp2, size=(sx, rsy))
tw(s.lmao, position=(0, rsy))
iw(s.yesbg, size=(sx, sy))
iw(s.yesbg2, size=(sx, 40), position=(20, sy-20))
2025-08-10 16:01:28 +03:00
# files
2025-08-10 13:02:22 +00:00
for i, _ in enumerate(fl):
2025-08-10 16:01:28 +03:00
if _ == sl:
2025-08-10 13:02:22 +00:00
s.sl = (i, _)
2025-08-10 16:01:28 +03:00
v = 15
hm = s.gdata(_)
for k in range(4):
j = rat[k]
e = h*j
2025-08-10 13:02:22 +00:00
ee = [30, 0][k != 0]
po = (v+ee, rsy-fly-fly*i)
2025-08-10 16:01:28 +03:00
t = tw(
parent=p,
2025-08-10 13:02:22 +00:00
size=(e-15-ee, fly),
2025-08-10 16:01:28 +03:00
position=po,
text=hm[k],
maxwidth=e-15-ee,
v_align='center',
selectable=True,
click_activate=True,
2025-08-10 13:02:22 +00:00
on_activate_call=Call(s._sl, i, _, fl),
2025-08-10 16:01:28 +03:00
glow_type='uniform',
allow_clear_button=False
)
if s.flon and u and not k:
ci = 0
bn = basename(_)
ret = []
while True:
2025-08-10 13:02:22 +00:00
nxt = bn.find(u, ci)
if nxt == -1:
break
2025-08-10 16:01:28 +03:00
bf = bn[:nxt]
ret.append(tw(
parent=p,
text=u,
2025-08-10 13:02:22 +00:00
position=(po[0]+GSW(bf), po[1]+3),
2025-08-10 16:01:28 +03:00
v_align='center'
))
ci = nxt + len(u)
s.flkids.append(ret)
if ee:
s.fcons.append(iw(
2025-08-10 13:02:22 +00:00
position=(po[0]-ee-8, po[1]+1),
2025-08-10 16:01:28 +03:00
texture=s.gtex(_),
2025-08-10 13:02:22 +00:00
size=(ee+1, ee+1),
2025-08-10 16:01:28 +03:00
parent=p
))
v += e
2025-08-10 13:02:22 +00:00
if k:
s.ftrash.append(t)
else:
s.fkids.append(t)
2025-08-10 16:01:28 +03:00
if _ == sl:
2025-08-10 13:02:22 +00:00
cw(s.yesp2, visible_child=t)
2025-08-10 16:01:28 +03:00
s.slco(fl)
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def onfl(s):
s.rfl = tw(query=s.fltxt)
if s.rfl != s.rflo:
s.rflo = s.rfl
s.fresh(sl=s.sl[1])
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def unfl(s):
s.flon = False
s.snd('deek')
s.fresh(sl=s.sl[1])
2025-08-10 13:02:22 +00:00
def gtex(s, _):
2025-08-10 16:01:28 +03:00
ty = s.gtype(_)
t = (
'replayIcon' if _ == '..' else
'folder' if isdir(_) else
'tv' if ty == 'Replay' else
'audioIcon' if ty == 'Audio' else
'graphicsIcon' if ty == 'Texture' else
'star' if ty == 'Mesh' else
'achievementOutline' if ty == 'Font' else
'file'
)
return gt(t)
2025-08-10 13:02:22 +00:00
def slco(s, fl):
2025-08-10 16:01:28 +03:00
# cancel rename
2025-08-10 13:02:22 +00:00
if s.clp == 4:
s.cancel()
2025-08-10 16:01:28 +03:00
sli = s.sl[0]
2025-08-10 13:02:22 +00:00
for i, g in enumerate(zip(fl, s.fkids, s.fcons)):
_, w, r = g
c = [(s.COL10, s.COL11), (s.COL8, s.COL9)][isdir(_)][sli == i]
tw(w, color=c, editable=False)
iw(r, color=c)
for i, z in enumerate(s.flkids):
2025-08-10 16:01:28 +03:00
for j in z:
2025-08-10 13:02:22 +00:00
tw(j, color=[s.COL0, s.COL3][sli == i])
def _sl(s, i, _, fl):
2025-08-10 16:01:28 +03:00
if s.sl[0] == i:
2025-08-10 13:02:22 +00:00
if isdir(_):
s.cd(_)
else:
s.act(0, 5, gay=True)
2025-08-10 16:01:28 +03:00
return
2025-08-10 13:02:22 +00:00
s.sl = (i, _)
2025-08-10 16:01:28 +03:00
s.slco(fl)
2025-08-10 13:02:22 +00:00
def gdata(s, _):
2025-08-10 16:01:28 +03:00
b = isdir(_)
2025-08-10 13:02:22 +00:00
try:
mt = DT.fromtimestamp(getmtime(_)).strftime('%m/%d/%Y %I:%M %p')
except:
mt = '?'
try:
sz = FMT(getsize(_))
except:
sz = '?'
2025-08-10 16:01:28 +03:00
return (
basename(_),
s.gtype(_),
'' if b else mt,
'' if b else sz
)
2025-08-10 13:02:22 +00:00
def gtype(s, _):
if isdir(_):
return ['Folder', 'Parent'][_ == '..']
2025-08-10 16:01:28 +03:00
f = 'File'
h = guess_type(_)[0] or f
2025-08-10 13:02:22 +00:00
if not '.' in _:
return h.title()
2025-08-10 16:01:28 +03:00
if h == f:
return {
2025-08-10 13:02:22 +00:00
'brp': 'Replay',
'bob': 'Mesh',
'cob': 'Mesh',
'ogg': 'Audio',
'ktx': 'Texture',
'fdata': 'Font'
}.get(_.split('.')[-1], f)
else:
return h.title()
2025-08-10 16:01:28 +03:00
def gfull(s):
c = var('cwd')
h = []
2025-08-10 13:02:22 +00:00
if dirname(c) != c:
h = ['..']
if not access(c, R_OK):
return h
items = [join(c, _) for _ in ls(c)]
2025-08-10 16:01:28 +03:00
da = {}
for item in items:
name, item_type, date_modified_str, _ = s.gdata(item)
try:
2025-08-10 13:02:22 +00:00
date_sortable = DT.strptime(
date_modified_str, '%m/%d/%Y %I:%M %p') if date_modified_str else DT.min
except:
date_sortable = DT.min
try:
mt = getmtime(item)
except:
mt = 0
2025-08-10 16:01:28 +03:00
da[item] = (basename(item).lower(), item_type.lower(), date_sortable, mt, isdir(item))
return h + sorted(items, key=lambda i: (
not da[i][4],
da[i][0] if s.sorti == 0 else
da[i][1] if s.sorti == 1 else
da[i][2] if s.sorti == 2 else
da[i][3]
))
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def pre(s):
s.wop()
r = s._pre()
xs = 200
ys = 160
pc = s.preb.get_screen_space_center()
p = s.prep = cw(
parent=zw('overlay_stack'),
background=False,
transition='in_scale',
scale_origin_stack_offset=pc,
2025-08-10 13:02:22 +00:00
on_outside_click_call=lambda: (cw(p, transition='out_scale'), s.laz()),
size=(xs, ys),
stack_offset=(pc[0]-xs/2+27, pc[1]-ys/2+27)
2025-08-10 16:01:28 +03:00
)
s.killme.append(p)
iw(
parent=p,
2025-08-10 13:02:22 +00:00
size=(xs*1.2, ys*1.2),
2025-08-10 16:01:28 +03:00
texture=gt('softRect'),
2025-08-10 13:02:22 +00:00
opacity=[0.2, 0.55][s.amoled],
position=(-xs*0.1, -ys*0.1),
2025-08-10 16:01:28 +03:00
color=s.COL5
)
iw(
parent=p,
2025-08-10 13:02:22 +00:00
size=(xs, ys),
2025-08-10 16:01:28 +03:00
texture=gt('white'),
color=s.COL1,
opacity=0.7
)
p2 = sw(
parent=p,
2025-08-10 13:02:22 +00:00
size=(xs, ys)
2025-08-10 16:01:28 +03:00
)
rys = 30*len(r)
p3 = cw(
parent=p2,
2025-08-10 13:02:22 +00:00
size=(xs, max(ys, rys)),
2025-08-10 16:01:28 +03:00
background=False
)
2025-08-10 13:02:22 +00:00
for i, _ in enumerate(r):
j, k = _
2025-08-10 16:01:28 +03:00
tw(
parent=p3,
2025-08-10 13:02:22 +00:00
size=(xs, 30),
position=(0, rys-30-30*i),
2025-08-10 16:01:28 +03:00
maxwidth=xs-20,
text=j,
click_activate=True,
selectable=True,
glow_type='uniform',
2025-08-10 13:02:22 +00:00
on_activate_call=Call(s.pres, k)
2025-08-10 16:01:28 +03:00
)
2025-08-10 13:02:22 +00:00
def pres(s, k):
2025-08-10 16:01:28 +03:00
GUN()
2025-08-10 13:02:22 +00:00
cw(s.prep, transition='out_scale')
2025-08-10 16:01:28 +03:00
s.cd(k)
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def _pre(s):
e = app.env
c = e.cache_directory
d = dirname
2025-08-10 13:02:22 +00:00
f = join(d(c), 'ballistica_files', 'ba_data')
2025-08-10 16:01:28 +03:00
g = cs(sc.LOGO_FLAT)+' '
return [
2025-08-10 13:02:22 +00:00
*[(cs(sc.DPAD_CENTER_BUTTON)+' '+(basename(_) or _), _) for _ in var('star')],
(g+'Mods', e.python_directory_user),
(g+'Replays', rdir()),
(g+'Config', e.config_directory),
(g+'Cache', c),
(g+'Files', f),
(g+'Python', join(f, 'python')),
(g+'Meshes', join(f, 'meshes')),
(g+'Audio', join(f, 'audio')),
(g+'Textures', join(f, 'textures'))
2025-08-10 16:01:28 +03:00
]
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def rf(s):
s.snd('ding')
s.fresh()
c = var('cwd')
s.push('Refreshed '+(basename(c) or c))
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def up(s):
o = var('cwd')
n = dirname(o)
if o == n:
s.eno = 2
s.nah()
s.snd('block')
return
s.cd(n)
s.snd('deek')
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def glike(s):
c = var('cwd')
2025-08-10 13:02:22 +00:00
if not access(c, R_OK):
s.eno = not access(c, X_OK)
2025-08-10 16:01:28 +03:00
s.nah()
return []
a = ls(c)
f = []
for _ in a:
2025-08-10 13:02:22 +00:00
j = join(c, _)
if isdir(j):
f.append(j)
2025-08-10 16:01:28 +03:00
r = [_ for _ in f if _.startswith(s.url)]
return r
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def nah(s):
2025-08-10 13:02:22 +00:00
if s.eno == s.leno:
return
2025-08-10 16:01:28 +03:00
s.leno = s.eno
s.push([
"I can't list files here! Write next folder name manually.",
"I can't even enter there! Select another folder.",
"Already reached root!"
2025-08-10 13:02:22 +00:00
][s.eno], color=s.enoc(), du=[3, 3, 2][s.eno])
2025-08-10 16:01:28 +03:00
def enoc(s):
return [
s.COL7,
s.COL4,
s.COL2
][s.eno]
2025-08-10 13:02:22 +00:00
def drop(s, i):
if s.gn:
return
s.dro = i > 0
2025-08-10 16:01:28 +03:00
s.droc()
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def droc(s):
s.drol = s.glike()
s.rdrop()
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def rdrop(s):
2025-08-10 13:02:22 +00:00
if s.gn:
return
2025-08-10 16:01:28 +03:00
[_.delete() for _ in s.drkids]
s.drkids.clear()
l = len(s.drol)
2025-08-10 13:02:22 +00:00
if not s.dro or not s.drol or (l == 1 and s.drol[0] == s.url):
iw(s.drbg, size=(0, 0))
sw(s.drp1, size=(0, 0))
2025-08-10 16:01:28 +03:00
return
2025-08-10 13:02:22 +00:00
x, y = s.size
2025-08-10 16:01:28 +03:00
of = 20
ys = 30*l+of
2025-08-10 13:02:22 +00:00
fys = min(300, ys)
2025-08-10 16:01:28 +03:00
yp = y-71-fys
xs = x-325
xp = 160
2025-08-10 13:02:22 +00:00
iw(s.drbg, size=(xs, fys), position=(xp, yp))
sw(s.drp1, size=(xs, fys), position=(xp, yp))
cw(s.drp2, size=(xs, ys-of))
for i, _ in enumerate(s.drol):
p = (0, ys-30-30*i-of)
2025-08-10 16:01:28 +03:00
s.drkids.append(tw(
parent=s.drp2,
position=p,
text=_,
color=s.COL9,
selectable=True,
click_activate=True,
glow_type='uniform',
2025-08-10 13:02:22 +00:00
on_activate_call=Call(s.cd, _),
size=(GSW(_), 30)
2025-08-10 16:01:28 +03:00
))
s.drkids.append(tw(
parent=s.drp2,
position=p,
text=s.url,
color=s.COL4,
))
2025-08-10 13:02:22 +00:00
def push(s, t, color=None, du=2):
if s.gn:
return
2025-08-10 16:01:28 +03:00
s.rly = False
s.rlydt = None
2025-08-10 13:02:22 +00:00
tw(s.pusht, color=color or s.COL2)
s.pushe = tuck(du, s.upush)
2025-08-10 16:01:28 +03:00
s.pushi = 0.05
s.pushq = t
s.rpush()
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def upush(s):
2025-08-10 13:02:22 +00:00
if s.gn:
return
2025-08-10 16:01:28 +03:00
s.pushi = -abs(s.pushi)
s.pushq = ''
s.rpush(1)
2025-08-10 13:02:22 +00:00
def rpush(s, mode=0):
if s.gn:
return
2025-08-10 16:01:28 +03:00
if mode:
2025-08-10 13:02:22 +00:00
tw(s.pusht, text=s.pushq, color=s.COL2)
2025-08-10 16:01:28 +03:00
return
x = s.size[0]
t = s.pushq
w = GSW(t+' '*3)
2025-08-10 13:02:22 +00:00
iw(s.pushbg, size=(w, 30), position=(x/2-w/2, 40))
iw(s.pushbg2, size=(w*1.1, 30*1.2), position=((x/2-w/2)-w*0.05, (40)-30*0.1))
tw(s.pusht, text=t, maxwidth=w*0.95, position=(x/2-25, 40))
2025-08-10 16:01:28 +03:00
def fpush(s):
2025-08-10 13:02:22 +00:00
if s.gn:
return
2025-08-10 16:01:28 +03:00
n = s.pusho + s.pushi
2025-08-10 13:02:22 +00:00
if not (1 >= n >= 0):
return
2025-08-10 16:01:28 +03:00
s.pusho = n
2025-08-10 13:02:22 +00:00
iw(s.pushbg, opacity=n)
iw(s.pushbg2, opacity=[n*0.4, n][s.amoled])
2025-08-10 16:01:28 +03:00
def urlbl(s):
2025-08-10 13:02:22 +00:00
if s.gn:
return
if s.p.get_selected_child() not in [s.ub, s.drp2, s.drp1, s.urlbg]+s.drkids:
2025-08-10 16:01:28 +03:00
s.urlbln = False
2025-08-10 13:02:22 +00:00
if s.dro:
s.drop(-1)
2025-08-10 16:01:28 +03:00
return
s.urlbln = not s.urlbln
2025-08-10 13:02:22 +00:00
if not s.dro:
s.drop(1)
2025-08-10 16:01:28 +03:00
def urlspy(s):
2025-08-10 13:02:22 +00:00
if s.gn:
return
2025-08-10 16:01:28 +03:00
s.url = tw(query=s.urla)
b1 = exists(s.url)
b2 = isdir(s.url)
2025-08-10 13:02:22 +00:00
g1 = access(var('cwd'), R_OK)
g2 = access(s.url, X_OK)
2025-08-10 16:01:28 +03:00
b = b1 and b2 and g1 and g2
av = not b1 and g1 and not g2 and s.drol
2025-08-10 13:02:22 +00:00
if b or av:
s.eno = None
2025-08-10 16:01:28 +03:00
q = s.url != s.urlo
2025-08-10 13:02:22 +00:00
if q:
s.droc()
2025-08-10 16:01:28 +03:00
lurl = var('cwd')
can = b1 and b2 and s.url != lurl
2025-08-10 13:02:22 +00:00
if can:
s.cd(s.url)
lurl = s.url
2025-08-10 16:01:28 +03:00
co = (
s.COL2 if b else
s.COL3 if av else
s.COL6 if not b1 else
s.enoc()
)
2025-08-10 13:02:22 +00:00
tw(s.urlt, text=s.url+[' ', '|'][s.urlbln or q], color=co)
2025-08-10 16:01:28 +03:00
s.urlo = s.url
2025-08-10 13:02:22 +00:00
if can or isdir(s.url):
return
2025-08-10 16:01:28 +03:00
# complete
f = dirname(s.url)
2025-08-10 13:02:22 +00:00
if not exists(f):
return
if f == lurl:
return
s.cd(f, dry=True)
def cd(s, t, dry=False):
if t == '..':
t = dirname(var('cwd'))
s.sl = (None, None)
2025-08-10 16:01:28 +03:00
if s.flon and s.rfl:
2025-08-10 13:02:22 +00:00
s.push("Filter is active! Press 'X' to cancel.", du=1.2, color=s.COL3)
var('cwd', t)
if s.eno != 1 and not access(t, X_OK):
2025-08-10 16:01:28 +03:00
s.eno = 1
s.nah()
2025-08-10 13:02:22 +00:00
0 if dry else tw(s.urla, text=t)
cw(s.yesp2, visible_child=s.lmao)
2025-08-10 16:01:28 +03:00
s.fresh()
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def urled(s):
2025-08-10 13:02:22 +00:00
if s.gn:
return
2025-08-10 16:01:28 +03:00
s.snd('deek')
s.urla.activate()
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def wop(s):
s.snd('powerup01')
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def laz(s):
s.snd('laser')
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
def bye(s):
s.gn = True
s.trash.clear()
s.laz()
s.main_window_back()
s.__class__.clean()
del s
2025-08-10 13:02:22 +00:00
def snd(s, t):
2025-08-10 16:01:28 +03:00
s.sn = gs(t)
s.sn.play()
2025-08-10 13:02:22 +00:00
teck(UF(0.13, 0.15), s.sn.stop)
2025-08-10 16:01:28 +03:00
def bga(s):
s.urlbln = False
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
# Tools and Resources
# Lambda means it won't be stored in memory unless called
2025-08-10 13:02:22 +00:00
def UI(): return app.ui_v1
def SCL(a, b, c=None): return [a, b, c][UI().uiscale.value] or b
def GSW(t): return strw(t, suppress_warning=True)
def GSH(t): return strh(t, suppress_warning=True)
def FMT(size): return (
2025-08-10 16:01:28 +03:00
f"{size / 1024**3:.1f} GB" if size >= 1024**3 else (
2025-08-10 13:02:22 +00:00
f"{size / 1024**2:.1f} MB" if size >= 1024**2 else (
f"{size / 1024:.1f} KB" if size >= 1024 else f"{size} B"))
2025-08-10 16:01:28 +03:00
)
2025-08-10 13:02:22 +00:00
def GUN(): return gs('gunCocking').play()
def BASE(): return join(dirname(app.env.cache_directory), 'ballistica_files', 'ba_data')
def AUDIO(): return ls(join(BASE(), 'audio'))
def TEX(): return ls(join(BASE(), 'textures'))
def SRT(): return ['Name', 'Type', 'Date Modifed', 'Size']
def INV(c): return ((1-c[0])*2, (1-c[1])*2, (1-c[2])*2)
def COL(): return [
(0.5, 0.5, 0),
(0.17, 0.17, 0.17),
(1, 1, 1),
(1, 1, 0),
(0.6, 0.6, 0.6),
(0, 0, 0),
(1, 0, 0),
(1, 0, 1),
(0.5, 0.25, 0),
(1, 0.5, 0),
(0, 0.5, 0.5),
(0, 1, 1)
2025-08-10 16:01:28 +03:00
]
# Config
2025-08-10 13:02:22 +00:00
def var(s, v=None):
cfg = app.config
s = 'fm_'+s
return cfg.get(s, v) if v is None else (cfg.__setitem__(s, v), cfg.commit())
def con(v, t):
if var(v) is None:
var(v, t)
2025-08-10 16:01:28 +03:00
# Default
2025-08-10 13:02:22 +00:00
con('cwd', getcwd())
con('star', [])
con('col', COL())
2025-08-10 16:01:28 +03:00
# Patches
2025-08-10 13:02:22 +00:00
f = SUB.on_screen_size_change
SUB.on_screen_size_change = lambda *a, **k: (FileMan.resize(), f(*a, **k))
bw = lambda *a, color=None, textcolor=None, oac=None, bg='white', label='', **k: obw(
2025-08-10 16:01:28 +03:00
*a,
on_activate_call=oac,
texture=gt(bg),
label=label,
enable_sound=False,
color=color or FileMan.COL1,
textcolor=textcolor or FileMan.COL2,
**k
)
# brobord collide grass
# ba_meta require api 9
# ba_meta export babase.Plugin
2025-08-10 13:02:22 +00:00
2025-08-10 16:01:28 +03:00
class byBordd(Plugin):
def on_app_running(s):
FileMan.loadc()
2025-08-10 13:02:22 +00:00
teck(0.1, s.kang)
2025-08-10 16:01:28 +03:00
def kang(s):
from bauiv1lib.settings.allsettings import AllSettingsWindow as m
i = '__init__'
2025-08-10 13:02:22 +00:00
o = getattr(m, i)
setattr(m, i, lambda z, *a, **k: (o(z, *a, **k), s.mk(z))[0])
def fix(s, p):
2025-08-10 16:01:28 +03:00
m = __import__('logging')
i = 'exception'
2025-08-10 13:02:22 +00:00
o = getattr(m, i)
setattr(m, i, lambda *a, **k: 0 if s.b == p.get_selected_child() else o(*a, **k))
def mk(s, z):
2025-08-10 16:01:28 +03:00
s.fix(z._root_widget)
2025-08-10 13:02:22 +00:00
x, y = SCL((1000, 800), (900, 450))
2025-08-10 16:01:28 +03:00
s.b = obw(
2025-08-10 13:02:22 +00:00
position=(x*0.7, y*SCL(0.5, 0.9)),
2025-08-10 16:01:28 +03:00
parent=z._root_widget,
icon=gt('folder'),
2025-08-10 13:02:22 +00:00
size=(100, 30),
2025-08-10 16:01:28 +03:00
button_type='square',
label='Man',
enable_sound=False,
color=FileMan.COL1,
textcolor=FileMan.COL2,
2025-08-10 13:02:22 +00:00
on_activate_call=lambda: s.run(z)
2025-08-10 16:01:28 +03:00
)
2025-08-10 13:02:22 +00:00
def run(s, z):
2025-08-10 16:01:28 +03:00
z.main_window_replace(new_window=FileMan(s.b))