mirror of
https://github.com/bombsquad-community/plugin-manager.git
synced 2025-10-08 14:54:36 +00:00
1771 lines
64 KiB
Python
Executable file
1771 lines
64 KiB
Python
Executable file
# 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
|
|
|
|
class FileMan(MainWindow):
|
|
VER = '1.0'
|
|
INS = []
|
|
@classmethod
|
|
def resize(c):
|
|
c.clean()
|
|
[_.on_resize() for _ in c.INS]
|
|
@classmethod
|
|
def clean(c):
|
|
c.INS = [_ for _ in c.INS if not _.gn and _.p.exists()]
|
|
@classmethod
|
|
def loadc(c):
|
|
[setattr(c,f'COL{i}',_) for i,_ in enumerate(var('col'))]
|
|
def __del__(s):
|
|
s.__class__.clean()
|
|
def on_resize(s):
|
|
[_.delete() for _ in s.killme]
|
|
s.killme.clear()
|
|
c = s.uploadc
|
|
s.spyt = s.sharel = s.buf = s.uploadc = None
|
|
if c: c.close()
|
|
s.fresh()
|
|
def __init__(s,src):
|
|
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
|
|
s.amoled = sum(s.COL5)==0
|
|
s.pusho = s.sorti = 0
|
|
s.pushi = -0.1
|
|
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']]
|
|
s.pushq = ''
|
|
# root
|
|
s.p = cw(
|
|
background=False,
|
|
toolbar_visibility='menu_minimal'
|
|
)
|
|
s.rect = iw(
|
|
texture=gt('softRect'),
|
|
opacity=[0.3,0.85][s.amoled],
|
|
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,
|
|
position=(-2,0),
|
|
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
|
|
) for _ in ['Action','Extra','New']]
|
|
# actions
|
|
s.gab = bw(
|
|
parent=s.p,
|
|
oac=s.cancel,
|
|
size=(0,0),
|
|
selectable=False
|
|
)
|
|
r = []
|
|
for _ in range(6):
|
|
l = ['Copy','Move','Delete','Share','Rename','Open'][_]
|
|
r.append(bw(
|
|
parent=s.p,
|
|
label=l,
|
|
oac=Call(s.act,0,_)
|
|
))
|
|
s.btns.append(r)
|
|
# extra
|
|
r = []
|
|
for _ in range(4):
|
|
l = ['Star','Sort','Filter','Theme'][_]
|
|
r.append(bw(
|
|
parent=s.p,
|
|
label=l,
|
|
oac=Call(s.act,1,_)
|
|
))
|
|
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,
|
|
size=(0,0),
|
|
selectable=False
|
|
)
|
|
# new
|
|
r = []
|
|
for _ in range(2):
|
|
l = ['File','Folder'][_]
|
|
r.append(bw(
|
|
parent=s.p,
|
|
label=l,
|
|
oac=Call(s.act,2,_)
|
|
))
|
|
s.btns.append(r)
|
|
# back
|
|
s.bb = bw(
|
|
parent=s.p,
|
|
label=' '+cs(sc.BACK),
|
|
oac=s.bye
|
|
)
|
|
cw(s.p,cancel_button=s.bb)
|
|
# 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,
|
|
size=(0,0),
|
|
parent=s.p,
|
|
text=s.url
|
|
)
|
|
s.trash.append(tuck(0.01,s.urlspy,repeat=True))
|
|
s.trash.append(tuck(0.1,s.urlbl,repeat=True))
|
|
# 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,
|
|
position=(20,20)
|
|
)
|
|
s.yesbg2 = iw(
|
|
parent=s.p,
|
|
texture=gt('white'),
|
|
color=s.COL5,
|
|
opacity=0.3,
|
|
)
|
|
s.yesp1 = sw(
|
|
parent=s.p,
|
|
border_opacity=0,
|
|
position=(17,20)
|
|
)
|
|
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'
|
|
)
|
|
s.trash.append(tuck(0.01,s.fpush,repeat=True))
|
|
# finally
|
|
s.fresh()
|
|
teck(0.5,lambda:s.push(f'FileMan v{s.VER} Ready!',du=1.5) if s.eno is None else 0)
|
|
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
|
|
def btw(s,t,du=3):
|
|
s.snd('block')
|
|
s.push(t,color=s.COL3,du=du)
|
|
def act(s,i,j,gay=False):
|
|
if s.gn: return
|
|
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')
|
|
chk = join(c,basename(s.clp))
|
|
st1,st2 = splitext(chk)
|
|
nn = st1+'_copy'+st2 if exists(chk) else chk
|
|
if exists(nn):
|
|
s.btw('A copy of this '+['file','folder'][isdir(chk)]+' already exists!')
|
|
return
|
|
try: [copy,copytree][isdir(s.clp)](s.clp,nn)
|
|
except Exception as e:
|
|
s.btw(str(e))
|
|
return
|
|
else:
|
|
GUN()
|
|
s.push('Pasted!')
|
|
s.clp = None
|
|
s.fresh()
|
|
else:
|
|
if s.meh(): return
|
|
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')
|
|
chk = join(c,basename(s.clp))
|
|
if exists(chk):
|
|
s.btw('There is a '+['file','folder'][isdir(chk)]+' with the same name here.')
|
|
return
|
|
try: move(s.clp,c)
|
|
except Exception as e:
|
|
s.btw(str(e))
|
|
return
|
|
else:
|
|
GUN()
|
|
s.push('Pasted!')
|
|
s.clp = None
|
|
s.fresh()
|
|
else:
|
|
if s.meh(): return
|
|
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
|
|
if s.meh(): return
|
|
h = s.sl[1]
|
|
bn = basename(h)
|
|
if not s.rlyd:
|
|
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))
|
|
s.rlyd = True
|
|
return
|
|
s.rlyd = False
|
|
s.rlydt = None
|
|
f = [remove,rmtree][isdir(h)]
|
|
try: f(h)
|
|
except Exception as e:
|
|
s.btw(str(e))
|
|
return
|
|
else:
|
|
GUN()
|
|
s.push('Deleted!')
|
|
s.sl = (None,None)
|
|
s.fresh()
|
|
case 3:
|
|
if s.meh(): return
|
|
f = s.sl[1]
|
|
if isdir(f):
|
|
s.btw("You can't share a folder!")
|
|
return
|
|
s.wop()
|
|
o = w.get_screen_space_center()
|
|
xs,ys = 400,170
|
|
p = s.uploadp = cw(
|
|
parent=zw('overlay_stack'),
|
|
scale_origin_stack_offset=o,
|
|
stack_offset=o,
|
|
size=(xs,ys),
|
|
background=False,
|
|
transition='in_scale'
|
|
)
|
|
s.killme.append(p)
|
|
iw(
|
|
parent=p,
|
|
size=(xs*1.2,ys*1.2),
|
|
texture=gt('softRect'),
|
|
opacity=[0.2,0.55][s.amoled],
|
|
position=(-xs*0.1,-ys*0.1),
|
|
color=s.COL5
|
|
)
|
|
iw(
|
|
parent=p,
|
|
texture=gt('white'),
|
|
color=s.COL1,
|
|
opacity=0.7,
|
|
size=(xs,ys)
|
|
)
|
|
bw(
|
|
parent=p,
|
|
label='Back',
|
|
oac=s.cupload,
|
|
position=(30,15),
|
|
size=(xs-60,30)
|
|
)
|
|
s.cpsharelb = bw(
|
|
parent=p,
|
|
label='...',
|
|
oac=s.cpsharel,
|
|
position=(30,50),
|
|
size=(xs-60,30)
|
|
)
|
|
s.opsharelb = bw(
|
|
parent=p,
|
|
label='...',
|
|
oac=s.opsharel,
|
|
position=(30,85),
|
|
size=(xs-60,30)
|
|
)
|
|
bw(
|
|
parent=p,
|
|
label='Upload to bashupload.com',
|
|
oac=s.upload,
|
|
position=(30,120),
|
|
size=(xs-60,30)
|
|
)
|
|
case 4:
|
|
if s.meh(): return
|
|
t = s.fkids[s.sl[0]]
|
|
fp = s.sl[1]
|
|
if s.clp == j:
|
|
q = tw(query=t)
|
|
try:
|
|
if sep in q: raise ValueError("You can't use directory separator in filename!")
|
|
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
|
|
chk = join(var('cwd'),q)
|
|
if exists(chk):
|
|
s.btw(f"There is a {['file','folder'][isdir(chk)]} with this name already!")
|
|
return
|
|
else:
|
|
nfp = join(dirname(fp),q)
|
|
try:
|
|
rename(fp,nfp)
|
|
except PermissionError:
|
|
if exists(nfp): pass
|
|
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
|
|
tw(t,editable=True,color=s.COL7)
|
|
cw(s.yesp2,visible_child=t)
|
|
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:
|
|
if s.meh(): return
|
|
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
|
|
gcen = lambda: ((o:=k.get_screen_space_center()),(o[0]-s.size[0]/5,o[1]) if gay else o)[1]
|
|
o = gcen()
|
|
xs,ys = [_*0.6 for _ in s.size]
|
|
p = cw(
|
|
parent=zw('overlay_stack'),
|
|
scale_origin_stack_offset=o,
|
|
size=(xs,ys),
|
|
background=False,
|
|
transition='in_scale'
|
|
)
|
|
s.killme.append(p)
|
|
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,ys)
|
|
)
|
|
b = bw(
|
|
parent=p,
|
|
position=(20,ys-70),
|
|
label=' '+cs(sc.BACK),
|
|
size=(50,50),
|
|
oac=Call(s.statbye,p,gcen)
|
|
)
|
|
cw(p,cancel_button=b)
|
|
ix = xs-250
|
|
iw(
|
|
parent=p,
|
|
texture=gt('white'),
|
|
color=s.COL1,
|
|
position=(90,ys-72),
|
|
size=(ix,54),
|
|
opacity=0.5
|
|
)
|
|
tw(
|
|
parent=p,
|
|
h_align='center',
|
|
v_align='center',
|
|
position=(xs/2-60,ys-60),
|
|
text=basename(h),
|
|
maxwidth=ix-100
|
|
)
|
|
iw(
|
|
parent=p,
|
|
texture=gt('white'),
|
|
color=s.COL1,
|
|
opacity=0.5,
|
|
position=(20,20),
|
|
size=(xs-40,ys-110)
|
|
)
|
|
bw(
|
|
parent=p,
|
|
label=cs(sc.REWIND_BUTTON),
|
|
position=(xs-141,ys-70),
|
|
size=(50,50),
|
|
oac=Call(s.stata,-1),
|
|
repeat=True
|
|
)
|
|
bw(
|
|
parent=p,
|
|
label=cs(sc.FAST_FORWARD_BUTTON),
|
|
position=(xs-71,ys-70),
|
|
size=(50,50),
|
|
oac=Call(s.stata,1),
|
|
repeat=True
|
|
)
|
|
s.oops = 0
|
|
try:
|
|
with open(h,'r') as f:
|
|
da = f.read()
|
|
except Exception as ex:
|
|
da = ''
|
|
s.oops = 1
|
|
if isinstance(ex,PermissionError): kek = 'Permission denied!'
|
|
elif isinstance(ex,UnicodeDecodeError): kek = 'No preview avaiable'
|
|
else: kek = str(ex)
|
|
else:
|
|
if not da:
|
|
s.oops = 1
|
|
kek = 'No data'
|
|
if not s.oops:
|
|
fxs = xs-40
|
|
fys = ys-110
|
|
s.statsz = (fxs,fys)
|
|
p0 = s.statp0 = sw(
|
|
parent=p,
|
|
position=(20,20),
|
|
size=(fxs,fys),
|
|
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,
|
|
position=(xs/2-20,ys-150),
|
|
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',
|
|
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)
|
|
)
|
|
elif ty == 'Texture' and bn in TEX():
|
|
wd = min(xs-80,ys-150)
|
|
tex = gt(splitext(bn)[0])
|
|
iw(
|
|
parent=p,
|
|
texture=tex,
|
|
size=(wd,wd),
|
|
position=(xs/2-wd/2,40)
|
|
)
|
|
elif ty == 'Audio' and bn in AUDIO():
|
|
tw(
|
|
parent=p,
|
|
position=(xs/2-20,ys-150),
|
|
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),
|
|
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)
|
|
)
|
|
bw(
|
|
parent=p,
|
|
label=cs(sc.PAUSE_BUTTON),
|
|
oac=lambda:getattr(s.cursnd,'stop',lambda:0)(),
|
|
position=(xs/2+30,ys/2-135),
|
|
size=(40,40)
|
|
)
|
|
else:
|
|
tw(
|
|
parent=p,
|
|
text=kek,
|
|
position=(xs/2-25,ys/2-35),
|
|
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)')
|
|
var('star',star)
|
|
GUN()
|
|
s.fresh(skip=True)
|
|
case 1:
|
|
xs,ys = 200,230
|
|
s.wop()
|
|
gcen = lambda: ((o:=w.get_screen_space_center()),(o[0]-s.size[0]/5,o[1]) if gay else o)[1]
|
|
o = gcen()
|
|
p = cw(
|
|
parent=zw('overlay_stack'),
|
|
scale_origin_stack_offset=o,
|
|
size=(xs,ys),
|
|
background=False,
|
|
transition='in_scale',
|
|
stack_offset=(o[0],o[1]),
|
|
on_outside_click_call=lambda:(cw(p,transition='out_scale'),s.laz())
|
|
)
|
|
s.killme.append(p)
|
|
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,ys)
|
|
)
|
|
by = 40
|
|
srt = SRT()
|
|
for _ in range(4):
|
|
bw(
|
|
position=(20,ys-20-by-(by+10)*_),
|
|
size=(xs-40,by),
|
|
label=srt[_],
|
|
oac=Call(s.surt,_,p),
|
|
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()
|
|
s.push('FileMan uses 12 main colors. Tap on a color to edit it. Press outside to cancel.',du=6)
|
|
o = w.get_screen_space_center()
|
|
def nuke():
|
|
cw(p,transition='out_scale')
|
|
s.laz()
|
|
s.push('Cancelled! Nothing was saved')
|
|
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')
|
|
s.killme.append(p)
|
|
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
|
|
kids, nubs, grad = [], [], []
|
|
def save():
|
|
if var('col') == temp_colors:
|
|
s.btw('At least change a color blud')
|
|
return
|
|
var('col',temp_colors)
|
|
GUN()
|
|
cw(p,transition='out_scale')
|
|
s.__class__.loadc()
|
|
s.bye()
|
|
SM('Reopen FileMan to see changes!')
|
|
def update_previews():
|
|
f3()
|
|
f4()
|
|
c = temp_colors[sl]
|
|
obw(kids[sl], color=c, textcolor=INV(c))
|
|
def f3():
|
|
[iw(l, position=(xs + scl[k] * ps - 16, 39 + qs * 5 - (qs) * k)) for k, l in enumerate(nubs)]
|
|
def f4():
|
|
c = temp_colors[sl]
|
|
[obw(l, color=(c[0] * (k / 19), c[1] * (k / 19), c[2] * (k / 19))) for k, l in enumerate(grad)]
|
|
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
|
|
temp_colors[sl] = new_color = (c[0] * scale, c[1] * scale, c[2] * scale)
|
|
scl[:3] = [int(x * 19) for x in new_color]
|
|
update_previews()
|
|
def f(z, sh=0):
|
|
nonlocal sl, scl
|
|
[obw(_, label='') for _ in kids]
|
|
obw(kids[z], label=cs(sc.DPAD_CENTER_BUTTON))
|
|
sl = z
|
|
if not sh: s.snd('deek')
|
|
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),
|
|
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) )
|
|
)
|
|
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)]
|
|
for x in range(4):
|
|
for y in range(3):
|
|
z = x * 3 + y
|
|
c = temp_colors[z]
|
|
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)
|
|
def reset():
|
|
mem = COL()
|
|
if mem == temp_colors:
|
|
s.btw("Reset what? It's already at default")
|
|
return
|
|
for i,m in enumerate(mem):
|
|
temp_colors[i] = m
|
|
update_previews()
|
|
GUN()
|
|
s.push('Restored default colors! now press save')
|
|
bw(parent=p, position=(xs + 5, 18.5), size=(172, qs - 3), label='Reset', oac=reset)
|
|
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')
|
|
n = join(c,'new_file')
|
|
while exists(n): n+='_again'
|
|
try: Path(n).touch()
|
|
except PermissionError:
|
|
s.btw('Permission denied!')
|
|
return
|
|
except Exception as ex:
|
|
s.btw(str(ex))
|
|
return
|
|
s.fresh(sl=n)
|
|
# rename
|
|
s.act(0,4,gay=True)
|
|
case 1:
|
|
if s.clpm:
|
|
s.btw("You're already in the middle of something")
|
|
return
|
|
c = var('cwd')
|
|
n = join(c,'new_folder')
|
|
while exists(n): n+='_again'
|
|
try: mkdir(n)
|
|
except PermissionError:
|
|
s.btw('Permission denied!')
|
|
return
|
|
except Exception as ex:
|
|
s.btw(str(ex))
|
|
return
|
|
s.fresh(sl=n)
|
|
# rename
|
|
s.act(0,4)
|
|
def surt(s,_,p):
|
|
if _ == s.sorti:
|
|
s.btw('Already sorted by '+SRT()[_]+'!')
|
|
return
|
|
s.sorti = _
|
|
GUN()
|
|
cw(p,transition='out_scale')
|
|
s.fresh(sl=s.sl[1])
|
|
def statbye(s,p,gcen):
|
|
try: cen = gcen()
|
|
except: p.delete()
|
|
else: cw(p,transition='out_scale',scale_origin_stack_offset=cen)
|
|
s.laz()
|
|
s.statda = None
|
|
s.statl = []
|
|
s.statp = 0
|
|
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))
|
|
s.COL_END_MARKER = getattr(s, 'COL_END_MARKER', (1.8, 0.6, 0.6)) # Neon Red for the marker
|
|
|
|
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)
|
|
lines = [_.replace('\\n','\\'+"~"+"n") for _ in da.splitlines()]
|
|
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
|
|
l = max(15,l)
|
|
l = min(l,20)
|
|
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
|
|
is_first_char_offset_applied = False # Flag for the critical offset
|
|
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:
|
|
po[0] -= l * 1.5; is_first_char_offset_applied = True
|
|
for c in end_marker:
|
|
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=s.COL_END_MARKER))
|
|
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:
|
|
po[0] -= l * 1.5; is_first_char_offset_applied = True
|
|
if not in_triple_comment:
|
|
in_triple_comment = True; triple_quote_char = chunk[0]
|
|
else:
|
|
in_triple_comment = False; triple_quote_char = None
|
|
for _ in range(3):
|
|
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
|
|
continue
|
|
|
|
# -- Priority 3: Newlines --
|
|
if i + 1 < z and da[i:i+2] == '\\n':
|
|
po[0] = pos[0]-l*1.5; po[1] -= hh; nc = 0
|
|
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:
|
|
po[0] -= l * 1.5; is_first_char_offset_applied = True
|
|
|
|
if in_triple_comment or mud:
|
|
big = nc < zc
|
|
color = (s.COL0 if big else s.COL3) if in_triple_comment else (s.COL10 if big else s.COL11)
|
|
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=color))
|
|
nc += 1; i += 1
|
|
continue
|
|
|
|
# -- Priority 5: Python Syntax Highlighting --
|
|
char = da[i]; token = char; token_color = s.COL2
|
|
if char in ("'", '"'):
|
|
k = i + 1
|
|
while k < z and (da[k] != char or da[k-1] == '\\'): k += 1
|
|
token = da[i:k+1]; token_color = s.COL_STRING
|
|
elif char.isdigit() or (char == '.' and i + 1 < z and da[i+1].isdigit()):
|
|
k = i
|
|
while k < z and (da[k].isdigit() or da[k] == '.'): k += 1
|
|
token = da[i:k]; token_color = s.COL_NUMBER
|
|
elif char.isalpha() or char == '_':
|
|
k = i
|
|
while k < z and (da[k].isalnum() or da[k] == '_'): k += 1
|
|
token = da[i:k]
|
|
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
|
|
|
|
for c in token:
|
|
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))
|
|
nc += 1
|
|
i += len(token)
|
|
|
|
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):
|
|
if not s.oops:
|
|
n = s.statp + s.stat*i
|
|
ok = len(s.statda)
|
|
if ok <= n:
|
|
s.btw('Reached EOF!',du=1)
|
|
return
|
|
if n < 0:
|
|
s.btw('Already at first chunk!',du=1)
|
|
return
|
|
s.snd('deek')
|
|
s.statp = n
|
|
if i<0: [s.statl.pop(-1) for _ in [0,0]]
|
|
s.itw()
|
|
else:
|
|
s.btw('No more open file buffers!')
|
|
def cpsharel(s):
|
|
l = s.vsharel()
|
|
if not l: return
|
|
COPY(str(l))
|
|
s.ding(1,1)
|
|
s.push(f"Copied '{l}' to clipboard!")
|
|
def opsharel(s):
|
|
l = s.vsharel()
|
|
if not l: return
|
|
s.snd('deek')
|
|
open_url(l)
|
|
def vsharel(s):
|
|
l = getattr(s,'sharel',0)
|
|
if not l:
|
|
s.btw("Upload first!")
|
|
return
|
|
return l
|
|
def cupload(s):
|
|
c = s.uploadc
|
|
s.spyt = s.sharel = s.buf = s.uploadc = None
|
|
if c:
|
|
c.close()
|
|
s.ding(0,0)
|
|
s.push('Cancelled!')
|
|
else: s.laz()
|
|
cw(s.uploadp,transition='out_scale')
|
|
def upload(s):
|
|
f = s.sl[1]
|
|
s.ding(1,0)
|
|
s.push('Uploading...')
|
|
Thread(target=Call(s._upload,f)).start()
|
|
s.spyt = tuck(0.2,Call(s.spy,s.on_upload),repeat=True)
|
|
def _upload(s, l):
|
|
try:
|
|
c = s.uploadc = GO('bashupload.com')
|
|
filename = basename(l)
|
|
url_path = '/' + filename
|
|
with open(l, 'rb') as f: body = f.read()
|
|
headers = {'Content-Type': 'application/octet-stream'}
|
|
c.request('POST', url_path, body=body, headers=headers)
|
|
s.buf = c.getresponse().read().decode()
|
|
except Exception:
|
|
if s.uploadc: s.buf = ''
|
|
finally:
|
|
if s.uploadc:
|
|
s.uploadc.close()
|
|
s.uploadc = s.sharel = None
|
|
def on_upload(s,t):
|
|
if not t:
|
|
s.btw("Couldn't upload")
|
|
return
|
|
s.sharel = t.splitlines()[5][5:]+'?download=1'
|
|
s.ding(0,1)
|
|
s.push('Success!')
|
|
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]
|
|
s.snd('ding'+x)
|
|
teck(0.1,gs('ding'+y).play)
|
|
def beep(s,i,j):
|
|
s.snd(f'raceBeep{str(i+1)}')
|
|
teck(0.1,gs(f'raceBeep{str(j+1)}').play)
|
|
def spy(s,f):
|
|
if s.buf is None: return
|
|
b = s.buf
|
|
s.buf = None
|
|
f(b)
|
|
s.spyt = None
|
|
def cancel(s):
|
|
c = s.clp
|
|
s.clp = None
|
|
s.push('Cancelled!')
|
|
s.snd('deek')
|
|
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
|
|
# root
|
|
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))
|
|
# docks, secs, btns
|
|
h = (x-80)
|
|
f = y-191
|
|
v = 18
|
|
for i in range(3):
|
|
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
|
|
for j in range(l):
|
|
for k in [0,l]:
|
|
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
|
|
po = v+of+(bh+20)*j,f+60-30*bool(k)
|
|
ww = a[j+k]
|
|
obw(ww,position=po,size=(zz,25))
|
|
if not ga:
|
|
if i == 1 and j == k == 0:
|
|
obw(ww,label=['Star','Unstar'][var('cwd') in var('star')])
|
|
elif i == 1 and j == 0 and k:
|
|
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]))
|
|
if s.flon:
|
|
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')
|
|
if not s.fltk:
|
|
s.rflo = s.fltk = ''
|
|
s.fltk = tuck(0.1,s.onfl,repeat=True)
|
|
else:
|
|
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='')
|
|
s.rfl = s.rflo = s.fltk = None
|
|
continue
|
|
he = bool(s.clp)
|
|
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
|
|
v += e+20
|
|
# back
|
|
f = y-70
|
|
obw(s.bb,position=(20,f),size=(50,50))
|
|
# up
|
|
obw(s.ub,position=(90,f),size=(50,50))
|
|
# url
|
|
e = x - 398
|
|
obw(s.urlbg,size=(e,50),position=(195,f))
|
|
tw(s.urlt,position=(180,y-60),maxwidth=x-370)
|
|
# rf
|
|
obw(s.rfb,position=(251+e,f),size=(50,50))
|
|
# pre
|
|
obw(s.preb,position=(323+e,f),size=(50,50))
|
|
# skip the rest
|
|
if skip: return
|
|
# drop
|
|
s.droc()
|
|
# oke
|
|
fly = 35
|
|
sx,sy = x-37,y-230
|
|
h = sx/6
|
|
v = 30
|
|
rat = [3,1,1,1]
|
|
for i,_ in enumerate(s.okes):
|
|
j = rat[i]
|
|
tw(_,position=(v+[30,0][i!=0],sy-15))
|
|
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:
|
|
if cur in fl: sl = cur
|
|
else: s.sl = (None,None)
|
|
# yes
|
|
rsy = len(fl)*fly
|
|
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))
|
|
# files
|
|
for i,_ in enumerate(fl):
|
|
if _ == sl:
|
|
s.sl = (i,_)
|
|
v = 15
|
|
hm = s.gdata(_)
|
|
for k in range(4):
|
|
j = rat[k]
|
|
e = h*j
|
|
ee = [30,0][k!=0]
|
|
po = (v+ee,rsy-fly-fly*i)
|
|
t = tw(
|
|
parent=p,
|
|
size=(e-15-ee,fly),
|
|
position=po,
|
|
text=hm[k],
|
|
maxwidth=e-15-ee,
|
|
v_align='center',
|
|
selectable=True,
|
|
click_activate=True,
|
|
on_activate_call=Call(s._sl,i,_,fl),
|
|
glow_type='uniform',
|
|
allow_clear_button=False
|
|
)
|
|
if s.flon and u and not k:
|
|
ci = 0
|
|
bn = basename(_)
|
|
ret = []
|
|
while True:
|
|
nxt = bn.find(u,ci)
|
|
if nxt == -1: break
|
|
bf = bn[:nxt]
|
|
ret.append(tw(
|
|
parent=p,
|
|
text=u,
|
|
position=(po[0]+GSW(bf),po[1]+3),
|
|
v_align='center'
|
|
))
|
|
ci = nxt + len(u)
|
|
s.flkids.append(ret)
|
|
if ee:
|
|
s.fcons.append(iw(
|
|
position=(po[0]-ee-8,po[1]+1),
|
|
texture=s.gtex(_),
|
|
size=(ee+1,ee+1),
|
|
parent=p
|
|
))
|
|
v += e
|
|
if k: s.ftrash.append(t)
|
|
else: s.fkids.append(t)
|
|
if _ == sl:
|
|
cw(s.yesp2,visible_child=t)
|
|
s.slco(fl)
|
|
def onfl(s):
|
|
s.rfl = tw(query=s.fltxt)
|
|
if s.rfl != s.rflo:
|
|
s.rflo = s.rfl
|
|
s.fresh(sl=s.sl[1])
|
|
def unfl(s):
|
|
s.flon = False
|
|
s.snd('deek')
|
|
s.fresh(sl=s.sl[1])
|
|
def gtex(s,_):
|
|
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)
|
|
def slco(s,fl):
|
|
# cancel rename
|
|
if s.clp == 4: s.cancel()
|
|
sli = s.sl[0]
|
|
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):
|
|
for j in z:
|
|
tw(j,color=[s.COL0,s.COL3][sli==i])
|
|
def _sl(s,i,_,fl):
|
|
if s.sl[0] == i:
|
|
if isdir(_): s.cd(_)
|
|
else: s.act(0,5,gay=True)
|
|
return
|
|
s.sl = (i,_)
|
|
s.slco(fl)
|
|
def gdata(s,_):
|
|
b = isdir(_)
|
|
try: mt = DT.fromtimestamp(getmtime(_)).strftime('%m/%d/%Y %I:%M %p')
|
|
except: mt = '?'
|
|
try: sz = FMT(getsize(_))
|
|
except: sz = '?'
|
|
return (
|
|
basename(_),
|
|
s.gtype(_),
|
|
'' if b else mt,
|
|
'' if b else sz
|
|
)
|
|
def gtype(s,_):
|
|
if isdir(_): return ['Folder','Parent'][_=='..']
|
|
f = 'File'
|
|
h = guess_type(_)[0] or f
|
|
if not '.' in _: return h.title()
|
|
if h == f:
|
|
return {
|
|
'brp':'Replay',
|
|
'bob':'Mesh',
|
|
'cob':'Mesh',
|
|
'ogg':'Audio',
|
|
'ktx':'Texture',
|
|
'fdata':'Font'
|
|
}.get(_.split('.')[-1],f)
|
|
else: return h.title()
|
|
def gfull(s):
|
|
c = var('cwd')
|
|
h = []
|
|
if dirname(c) != c: h = ['..']
|
|
if not access(c, R_OK): return h
|
|
items = [join(c,_) for _ in ls(c)]
|
|
da = {}
|
|
for item in items:
|
|
name, item_type, date_modified_str, _ = s.gdata(item)
|
|
try:
|
|
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
|
|
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]
|
|
))
|
|
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,
|
|
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)
|
|
)
|
|
s.killme.append(p)
|
|
iw(
|
|
parent=p,
|
|
size=(xs*1.2,ys*1.2),
|
|
texture=gt('softRect'),
|
|
opacity=[0.2,0.55][s.amoled],
|
|
position=(-xs*0.1,-ys*0.1),
|
|
color=s.COL5
|
|
)
|
|
iw(
|
|
parent=p,
|
|
size=(xs,ys),
|
|
texture=gt('white'),
|
|
color=s.COL1,
|
|
opacity=0.7
|
|
)
|
|
p2 = sw(
|
|
parent=p,
|
|
size=(xs,ys)
|
|
)
|
|
rys = 30*len(r)
|
|
p3 = cw(
|
|
parent=p2,
|
|
size=(xs,max(ys,rys)),
|
|
background=False
|
|
)
|
|
for i,_ in enumerate(r):
|
|
j,k = _
|
|
tw(
|
|
parent=p3,
|
|
size=(xs,30),
|
|
position=(0,rys-30-30*i),
|
|
maxwidth=xs-20,
|
|
text=j,
|
|
click_activate=True,
|
|
selectable=True,
|
|
glow_type='uniform',
|
|
on_activate_call=Call(s.pres,k)
|
|
)
|
|
def pres(s,k):
|
|
GUN()
|
|
cw(s.prep,transition='out_scale')
|
|
s.cd(k)
|
|
def _pre(s):
|
|
e = app.env
|
|
c = e.cache_directory
|
|
d = dirname
|
|
f = join(d(c),'ballistica_files','ba_data')
|
|
g = cs(sc.LOGO_FLAT)+' '
|
|
return [
|
|
*[(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'))
|
|
]
|
|
def rf(s):
|
|
s.snd('ding')
|
|
s.fresh()
|
|
c = var('cwd')
|
|
s.push('Refreshed '+(basename(c) or c))
|
|
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')
|
|
def glike(s):
|
|
c = var('cwd')
|
|
if not access(c,R_OK):
|
|
s.eno = not access(c,X_OK)
|
|
s.nah()
|
|
return []
|
|
a = ls(c)
|
|
f = []
|
|
for _ in a:
|
|
j = join(c,_)
|
|
if isdir(j): f.append(j)
|
|
r = [_ for _ in f if _.startswith(s.url)]
|
|
return r
|
|
def nah(s):
|
|
if s.eno == s.leno: return
|
|
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!"
|
|
][s.eno],color=s.enoc(),du=[3,3,2][s.eno])
|
|
def enoc(s):
|
|
return [
|
|
s.COL7,
|
|
s.COL4,
|
|
s.COL2
|
|
][s.eno]
|
|
def drop(s,i):
|
|
if s.gn: return
|
|
s.dro = i>0
|
|
s.droc()
|
|
def droc(s):
|
|
s.drol = s.glike()
|
|
s.rdrop()
|
|
def rdrop(s):
|
|
if s.gn: return
|
|
[_.delete() for _ in s.drkids]
|
|
s.drkids.clear()
|
|
l = len(s.drol)
|
|
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))
|
|
return
|
|
x,y = s.size
|
|
of = 20
|
|
ys = 30*l+of
|
|
fys = min(300,ys)
|
|
yp = y-71-fys
|
|
xs = x-325
|
|
xp = 160
|
|
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)
|
|
s.drkids.append(tw(
|
|
parent=s.drp2,
|
|
position=p,
|
|
text=_,
|
|
color=s.COL9,
|
|
selectable=True,
|
|
click_activate=True,
|
|
glow_type='uniform',
|
|
on_activate_call=Call(s.cd,_),
|
|
size=(GSW(_),30)
|
|
))
|
|
s.drkids.append(tw(
|
|
parent=s.drp2,
|
|
position=p,
|
|
text=s.url,
|
|
color=s.COL4,
|
|
))
|
|
def push(s,t,color=None,du=2):
|
|
if s.gn: return
|
|
s.rly = False
|
|
s.rlydt = None
|
|
tw(s.pusht,color=color or s.COL2)
|
|
s.pushe = tuck(du,s.upush)
|
|
s.pushi = 0.05
|
|
s.pushq = t
|
|
s.rpush()
|
|
def upush(s):
|
|
if s.gn: return
|
|
s.pushi = -abs(s.pushi)
|
|
s.pushq = ''
|
|
s.rpush(1)
|
|
def rpush(s,mode=0):
|
|
if s.gn: return
|
|
if mode:
|
|
tw(s.pusht,text=s.pushq,color=s.COL2)
|
|
return
|
|
x = s.size[0]
|
|
t = s.pushq
|
|
w = GSW(t+' '*3)
|
|
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))
|
|
def fpush(s):
|
|
if s.gn: return
|
|
n = s.pusho + s.pushi
|
|
if not (1 >= n >= 0): return
|
|
s.pusho = n
|
|
iw(s.pushbg,opacity=n)
|
|
iw(s.pushbg2,opacity=[n*0.4,n][s.amoled])
|
|
def urlbl(s):
|
|
if s.gn: return
|
|
if s.p.get_selected_child() not in [s.ub,s.drp2,s.drp1,s.urlbg]+s.drkids:
|
|
s.urlbln = False
|
|
if s.dro: s.drop(-1)
|
|
return
|
|
s.urlbln = not s.urlbln
|
|
if not s.dro: s.drop(1)
|
|
def urlspy(s):
|
|
if s.gn: return
|
|
s.url = tw(query=s.urla)
|
|
b1 = exists(s.url)
|
|
b2 = isdir(s.url)
|
|
g1 = access(var('cwd'),R_OK)
|
|
g2 = access(s.url,X_OK)
|
|
b = b1 and b2 and g1 and g2
|
|
av = not b1 and g1 and not g2 and s.drol
|
|
if b or av: s.eno = None
|
|
q = s.url != s.urlo
|
|
if q: s.droc()
|
|
lurl = var('cwd')
|
|
can = b1 and b2 and s.url != lurl
|
|
if can: s.cd(s.url); lurl = s.url
|
|
co = (
|
|
s.COL2 if b else
|
|
s.COL3 if av else
|
|
s.COL6 if not b1 else
|
|
s.enoc()
|
|
)
|
|
tw(s.urlt,text=s.url+[' ','|'][s.urlbln or q],color=co)
|
|
s.urlo = s.url
|
|
if can or isdir(s.url): return
|
|
# complete
|
|
f = dirname(s.url)
|
|
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)
|
|
if s.flon and s.rfl:
|
|
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):
|
|
s.eno = 1
|
|
s.nah()
|
|
0 if dry else tw(s.urla,text=t)
|
|
cw(s.yesp2,visible_child=s.lmao)
|
|
s.fresh()
|
|
def urled(s):
|
|
if s.gn: return
|
|
s.snd('deek')
|
|
s.urla.activate()
|
|
def wop(s):
|
|
s.snd('powerup01')
|
|
def laz(s):
|
|
s.snd('laser')
|
|
def bye(s):
|
|
s.gn = True
|
|
s.trash.clear()
|
|
s.laz()
|
|
s.main_window_back()
|
|
s.__class__.clean()
|
|
del s
|
|
def snd(s,t):
|
|
s.sn = gs(t)
|
|
s.sn.play()
|
|
teck(UF(0.13,0.15),s.sn.stop)
|
|
def bga(s):
|
|
s.urlbln = False
|
|
|
|
# Tools and Resources
|
|
# Lambda means it won't be stored in memory unless called
|
|
UI = lambda: app.ui_v1
|
|
SCL = lambda a,b,c=None: [a,b,c][UI().uiscale.value] or b
|
|
GSW = lambda t: strw(t,suppress_warning=True)
|
|
GSH = lambda t: strh(t,suppress_warning=True)
|
|
FMT = lambda size: (
|
|
f"{size / 1024**3:.1f} GB" if size >= 1024**3 else (
|
|
f"{size / 1024**2:.1f} MB" if size >= 1024**2 else (
|
|
f"{size / 1024:.1f} KB" if size >= 1024 else f"{size} B"))
|
|
)
|
|
GUN = lambda: gs('gunCocking').play()
|
|
BASE = lambda: join(dirname(app.env.cache_directory),'ballistica_files','ba_data')
|
|
AUDIO = lambda: ls(join(BASE(),'audio'))
|
|
TEX = lambda: ls(join(BASE(),'textures'))
|
|
SRT = lambda: ['Name','Type','Date Modifed','Size']
|
|
INV = lambda c: ((1-c[0])*2,(1-c[1])*2,(1-c[2])*2)
|
|
COL = lambda: [
|
|
(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)
|
|
]
|
|
|
|
# Config
|
|
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)
|
|
|
|
# Default
|
|
con('cwd',getcwd())
|
|
con('star',[])
|
|
con('col',COL())
|
|
|
|
# Patches
|
|
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(
|
|
*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
|
|
class byBordd(Plugin):
|
|
def on_app_running(s):
|
|
FileMan.loadc()
|
|
teck(0.1,s.kang)
|
|
def kang(s):
|
|
from bauiv1lib.settings.allsettings import AllSettingsWindow as m
|
|
i = '__init__'
|
|
o = getattr(m,i)
|
|
setattr(m,i,lambda z,*a,**k:(o(z,*a,**k),s.mk(z))[0])
|
|
def fix(s,p):
|
|
m = __import__('logging')
|
|
i = 'exception'
|
|
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):
|
|
s.fix(z._root_widget)
|
|
x,y = SCL((1000,800),(900,450))
|
|
s.b = obw(
|
|
position=(x*0.7,y*SCL(0.5,0.9)),
|
|
parent=z._root_widget,
|
|
icon=gt('folder'),
|
|
size=(100,30),
|
|
button_type='square',
|
|
label='Man',
|
|
enable_sound=False,
|
|
color=FileMan.COL1,
|
|
textcolor=FileMan.COL2,
|
|
on_activate_call=lambda:s.run(z)
|
|
)
|
|
def run(s,z):
|
|
z.main_window_replace(new_window=FileMan(s.b))
|