CurrentLanguage=nil CurrentLanguageCode="en" function loadLanguage(langCode)print("Loading language: "..langCode)CurrentLanguage=nil collectgarbage()local langFile="/base_path/lang_"..langCode..".lua" print("Attempting to load file: "..langFile)local chunk,errorMsg=loadfile(langFile)if chunk then print("File loaded successfully, executing...")local success,result=pcall(chunk)if success then CurrentLanguage=result CurrentLanguageCode=langCode print("Language loaded successfully: "..langCode)return true else print("Error executing language file: "..tostring(result))CurrentLanguage=nil return false end else print("Failed to load language file: "..langFile)if errorMsg then print("Error: "..errorMsg)end if not CurrentLanguage then print("Loading fallback English language")local enChunk,enError=loadfile("/base_path/lang_en.lua")if enChunk then local success,result=pcall(enChunk)if success then CurrentLanguage=result CurrentLanguageCode="en" print("Fallback English loaded successfully")else print("Error executing English fallback: "..tostring(result))end else print("Failed to load English fallback: "..tostring(enError))end end return false end end function getAvailableLanguages()local availableLanguages={}for code,langData in pairs(Languages)do table.insert(availableLanguages,{code=code,displayName=langData._displayName})end return availableLanguages end Settings=require("settings")Languages=require("languages")print("Initializing language system...")local defaultLang=UI.getLanguagePreference()or "en" local searchState=nil Settings.language=defaultLang if not loadLanguage(defaultLang)then print("Failed to load preferred language, falling back to English")loadLanguage("en")end print("Language system initialized with: "..CurrentLanguageCode)local KEY_CTRL_SPACE=0xFF local KEY_CTRL_A=0x01 local KEY_CTRL_L=0x0C local KEY_CTRL_S=0x13 local KEY_CTRL_U=0x15 local KEY_CTRL_T=0x14 local KEY_CTRL_N=0x0E local KEY_CTRL_O=0x0F local KEY_CTRL_F=0x06 local KEY_CTRL_G=0x07 local KEY_CTRL_SLASH=0x1F local KEY_ESCAPE=0x1B local TIMEOUT_BT_SCAN_MS=25000 local TIMEOUT_SYNC_MS=60000 local TIMEOUT_CONNECT_MS=10000 local TIMEOUT_SYNC_FAILED_MS=5000 local DELAY_ABOUT_DIALOG_MS=8000 local DELAY_BT_UI_MS=250 local ContextStack={stack={},push=function(self,contextType,data)local context={type=contextType,data=data or{},timestamp=os.time()}table.insert(self.stack,context)return context end,pop=function(self)if#self.stack>0 then return table.remove(self.stack)end return nil end,current=function(self)if#self.stack>0 then return self.stack[#self.stack]end return nil end,reset=function(self,newContextType,newData)self.stack={}if newContextType then self:push(newContextType,newData)end end,wipe=function(self)self.stack={}end,clean=function(self)if#self.stack>1 then local lastContext=self.stack[#self.stack]self.stack={lastContext}end end,depth=function(self)return#self.stack end,findContextOfType=function(self,contextType)for i=#self.stack,1,-1 do if self.stack[i].type==contextType then return self.stack[i],i end end return nil end,removeContextOfType=function(self,contextType)local _,index=self:findContextOfType(contextType)if index then return table.remove(self.stack,index)end return nil end,removeAllContextsOfType=function(self,contextType)local removed={}for i=#self.stack,1,-1 do if self.stack[i].type==contextType then table.insert(removed,table.remove(self.stack,i))end end return removed end,hasContextType=function(self,contextType)return self:findContextOfType(contextType)~=nil end,printStack=function(self)print("Context Stack:")for i,context in ipairs(self.stack)do print(string.format("%d: %s %s",i,context.type,context.data and tostring(context.data)or ""))end end}local MenuState={current=nil,menuParent=nil,getParent=function(self,menuId)if not self.menuParent then self.menuParent={[MENU.FILE]=MENU.MAIN,[MENU.CONNECTIONS]=MENU.MAIN,[MENU.BT]=MENU.CONNECTIONS,[MENU.WIFI]=MENU.CONNECTIONS,[MENU.WIFI_DISABLED]=MENU.CONNECTIONS,[MENU.SYNC]=MENU.CONNECTIONS,[MENU.SETTINGS]=MENU.MAIN,}end return self.menuParent[menuId]or MENU.MAIN end,show=function(self,menuId)self.current=menuId if not ContextStack:hasContextType("menu")then ContextStack:push("menu",{menuId=menuId})else local menuContext=ContextStack:findContextOfType("menu")if menuContext then menuContext.data.menuId=menuId end end MENU.show(menuId)end,showWithName=function(self,menuId,deviceName)self.current=menuId if not ContextStack:hasContextType("menu")then ContextStack:push("menu",{menuId=menuId,deviceName=deviceName})else local menuContext=ContextStack:findContextOfType("menu")if menuContext then menuContext.data.menuId=menuId menuContext.data.deviceName=deviceName end end MENU.showWithName(menuId,deviceName)end,back=function(self)local parent=self:getParent(self.current)self.current=parent MENU.show(parent)end,close=function(self)MENU.hide()ContextStack:removeContextOfType("menu")local currentContext=ContextStack:current()if currentContext and currentContext.type=="editor" then UI.returnToEditor()else end end}local function showNotification(title,message,contextData)ContextStack:removeAllContextsOfType("notification")ContextStack:push("notification",contextData or{title=title,message=message})UI.showNotification(title,message)end local function showNotificationWithTimeout(title,message,contextData,timeoutMs)ContextStack:removeAllContextsOfType("notification")ContextStack:push("notification",contextData or{title=title,message=message})UI.showNotificationWithTimeout(title,message,timeoutMs)end local function hideNotification()if ContextStack:hasContextType("notification")then UI.hideNotification()ContextStack:removeAllContextsOfType("notification")end end local function showBasicAlert(title,message,contextType)local alertType=contextType or "basicAlert" ContextStack:removeAllContextsOfType(alertType)ContextStack:push(alertType,{title=title,message=message,alertType="basic"})UI.showBasicAlert(title,message)end local function showConfirmAlert(title,message,contextType)local alertType=contextType or "confirmAlert" ContextStack:removeAllContextsOfType(alertType)ContextStack:push(alertType,{title=title,message=message,alertType="confirm"})UI.showConfirmAlert(title,message)end local function showList(listType)local n=UI.showList(listType)if n>0 then ContextStack:removeAllContextsOfType("list")ContextStack:push("list",{listType=listType})end return n end local function pairKB()ContextStack:push("btPairing")showNotificationWithTimeout(tr("bt"),tr("scan"),{type="btScanning"},TIMEOUT_BT_SCAN_MS)SYS.scanBTKeyboards()end local function disconnectBT()SYS.disconnectBTKeyboard()MenuState:show(MENU.BT)end local function openEditor(filename)local success=UI.openEditor(filename)if success==true then if ContextStack:hasContextType("editor")then local editorContext=ContextStack:findContextOfType("editor")if editorContext and editorContext.data.fileName~=filename then editorContext.data.fileName=filename end else ContextStack:push("editor",{fileName=filename})end else showBasicAlert(tr("file"),tr("offail"),"fileOpenError")end end local function openEditorByFileId(fileId)local success=UI.openEditorByFileId(fileId)if success==true then if ContextStack:hasContextType("editor")then local editorContext=ContextStack:findContextOfType("editor")if editorContext then editorContext.data.fileId=fileId editorContext.data.fileName=nil end else ContextStack:push("editor",{fileId=fileId,fileName=nil})end return true else return false end end local function enterDiskMode()if ContextStack:hasContextType("editor")then UI.closeEditor()ContextStack:removeContextOfType("editor")end ContextStack:push("diskMode")SYS.diskMode()end local function newFile()if not SYS.isCurrentProject()then showBasicAlert(tr("file"),tr("scp"),"fileError")else ContextStack:push("newFile")UI.showEntryFiltered(tr("file"),"")end end local function openFile()if not SYS.isCurrentProject()then showBasicAlert(tr("file"),tr("scp"),"fileError")else ContextStack:push("openFile")local count=showList(UI.FILE_LIST)if count==0 then ContextStack:pop()showBasicAlert(tr("file"),tr("nfound"),"fileError")end end end local function newProject()ContextStack:push("newProject")UI.showEntryFiltered(tr("np"),"")end local function openProject()ContextStack:push("openProject")local count=showList(UI.PROJECT_LIST)if count==0 then ContextStack:pop()showBasicAlert(tr("proj"),tr("scp"),"projectError")end end local function deleteFile()if not SYS.isCurrentProject()then showBasicAlert(tr("file"),tr("scp"),"fileError")else ContextStack:push("deleteFile")local count=showList(UI.FILE_LIST)if count==0 then ContextStack:pop()showBasicAlert(tr("file"),tr("nfound"),"fileError")end end end local function fontList()ContextStack:push("fontList")UI.showFontList()end local function showContrast()ContextStack:push("contrast")UI.showContrastDialog()end local function bluetoothMenu()local name=SYS.getConnectedKeyboardName()if name=="" then MenuState:show(MENU.BT)else MenuState:showWithName(MENU.BT,name)end end local function knownAPs()local n=showList(UI.WIFI_LIST_KNOWN)if(n==0)then showBasicAlert(tr("wifi"),tr("noaps"),"wifiError")end end local function setUpWifi()print("Setting up WiFi")local n=showList(UI.WIFI_LIST_SCAN)if(n==0)then showBasicAlert(tr("wifi"),tr("nowifi"),"wifiError")end end local function showLanguage()showList(UI.LANGUAGE_LIST)end local function showSyncSetup()if not SYS.getWiFiEnabled()or SYS.getConnectedWiFiName()=="" then showBasicAlert(tr("wifi"),tr("wififail"),"wifiError")return end ContextStack:push("syncSetup")local registrationCode=SYS.getRegistrationCode()showConfirmAlert(tr("syncsetup"),registrationCode,"syncSetup")end local function syncDisconnect()ContextStack:push("syncDisconnect")showConfirmAlert(tr("sync"),tr("dissync"),"syncDisconnect")end local function syncMenu()if SYS.isProvisioned()then MenuState:showWithName(MENU.SYNC,tr("sync_act"))else MenuState:show(MENU.SYNC)end end local function wifiMenu()if not SYS.getWiFiEnabled()then MenuState:show(MENU.WIFI_DISABLED)return end local name=SYS.getConnectedWiFiName()if name~="" then MenuState:showWithName(MENU.WIFI,tr("use")..name)else MenuState:show(MENU.WIFI)end end local function wifiOnOff()local enabled=SYS.getWiFiEnabled()if enabled then SYS.setWiFiEnabled(false)else SYS.setWiFiEnabled(true)end wifiMenu()end local function wifiDisconnect()SYS.disconnectKnownWifi()wifiMenu()end local function syncNow()local savedBufferPos=nil if ContextStack:hasContextType("editor")then savedBufferPos=UI.getEditorBufferPosition()UI.closeEditor()ContextStack:removeContextOfType("editor")end if ContextStack:hasContextType("menu")then MENU.hide()ContextStack:removeContextOfType("menu")end showNotificationWithTimeout(tr(""),tr("syncing"),{type="syncing"},TIMEOUT_SYNC_MS)ContextStack:push("sync",{bufferPos=savedBufferPos})SYS.sync()end local function tryReopenEditorAfterSync(syncCtx)if not syncCtx or not syncCtx.data then ContextStack:push("menu",{menuId=MENU.MAIN})MenuState:show(MENU.MAIN)return end if syncCtx.data.bufferPos==nil then ContextStack:push("menu",{menuId=MENU.MAIN})MenuState:show(MENU.MAIN)return end local fileId=SYS.getLastOpenedFileId()if fileId=="" then ContextStack:push("menu",{menuId=MENU.MAIN})MenuState:show(MENU.MAIN)return end local ok=UI.openEditorByFileIdAtPosition(fileId,syncCtx.data.bufferPos)if ok then ContextStack:push("editor",{fileId=fileId})else SYS.setLastOpenedFileId("")ContextStack:push("menu",{menuId=MENU.MAIN})MenuState:show(MENU.MAIN)end end local function closeMenu()if ContextStack:hasContextType("editor")then MenuState:close()end end local menuEventHandlers={[MENU.EVENT_FILE]=function()MenuState:show(MENU.FILE)end,[MENU.EVENT_BT]=function()bluetoothMenu()end,[MENU.EVENT_WIFI]=function()wifiMenu()end,[MENU.EVENT_SYNC]=function()syncMenu()end,[MENU.EVENT_SETTINGS]=function()MenuState:show(MENU.SETTINGS)end,[MENU.EVENT_CONNECTIONS]=function()MenuState:show(MENU.CONNECTIONS)end,[MENU.EVENT_BACK]=function()MenuState:back()end,[MENU.EVENT_CLOSE]=function()closeMenu()end,[MENU.EVENT_BT_DEVICES]=function()showList(UI.BT_LIST_KNOWN)end,[MENU.EVENT_WIFI_DEVICES]=function()knownAPs()end,[MENU.EVENT_WIFI_SETUP]=function()setUpWifi()end,[MENU.EVENT_WIFI_ONOFF]=function()wifiOnOff()end,[MENU.EVENT_WIFI_DISCONNECT]=function()wifiDisconnect()end,[MENU.EVENT_BT_PAIR]=function()pairKB()end,[MENU.EVENT_BT_DISCONNECT]=function()disconnectBT()end,[MENU.EVENT_NEW_FILE]=function()newFile()end,[MENU.EVENT_OPEN_FILE]=function()openFile()end,[MENU.EVENT_NEW_PROJECT]=function()newProject()end,[MENU.EVENT_OPEN_PROJECT]=function()openProject()end,[MENU.EVENT_DEL_FILE]=function()deleteFile()end,[MENU.EVENT_SETTINGS_DISK]=function()enterDiskMode()end,[MENU.EVENT_SETTINGS_FONT]=function()fontList()end,[MENU.EVENT_SETTINGS_CONTRAST]=function()showContrast()end,[MENU.EVENT_SETTINGS_LANGUAGE]=function()showLanguage()end,[MENU.EVENT_SETTINGS_KEYBOARD]=function()showList(UI.KEYBOARD_LAYOUT_LIST)end,[MENU.EVENT_SETTINGS_CURSOR]=function()showList(UI.CURSOR_LIST)end,[MENU.EVENT_WIFI_CHECK_UPDATE]=function()SYS.checkUpdate()end,[MENU.EVENT_SYNC_NOW]=function()syncNow()end,[MENU.EVENT_SYNC_SETUP]=function()showSyncSetup()end,[MENU.EVENT_SYNC_DISCONNECT]=function()syncDisconnect()end,}local currentKeyInfo=nil local keyHandlers={[KEY_CTRL_SPACE]=function()local statusVisible=not ContextStack:hasContextType("statusBar")if statusVisible then ContextStack:push("statusBar")UI.showStatusBar()else ContextStack:removeContextOfType("statusBar")UI.hideStatusBar()end return true end,[KEY_CTRL_F]=function()if not ContextStack:hasContextType("editor")then return false end searchState=nil ContextStack:push("editorSearch")UI.showEntry(tr("find"),"")return true end,[KEY_CTRL_G]=function()if not searchState then return false end local nextStart=0 if searchState.lastMatchPos and searchState.lastMatchPos>=0 then nextStart=searchState.lastMatchPos+1 else nextStart=UI.getEditorBufferPosition()end local matchPos=UI.searchEditorForward(searchState.term,nextStart)if matchPos<0 then matchPos=UI.searchEditorForward(searchState.term,0)end if matchPos>=0 then searchState.lastMatchPos=matchPos UI.jumpEditorToPosition(matchPos,searchState.termLen)end return true end,[KEY_CTRL_S]=function()syncNow()return true end,[KEY_CTRL_T]=function()print("Ctrl-T pressed: Tools")return true end,[KEY_CTRL_N]=function()if ContextStack:hasContextType("list")then return true end if currentKeyInfo and currentKeyInfo.is_shift then newProject()else newFile()end return true end,[KEY_CTRL_O]=function()if ContextStack:hasContextType("list")then return true end if currentKeyInfo and currentKeyInfo.is_shift then openProject()else openFile()end return true end,[KEY_CTRL_L]=function()SYS.changeBacklight()return true end,[KEY_ESCAPE]=function()local frontContext=ContextStack:current()if frontContext then if frontContext.type=="editor" then MenuState:show(MENU.MAIN)return true end if frontContext.type=="menu" then local editorContext=ContextStack:findContextOfType("editor")if editorContext then MenuState:close()return true end end end return true end}local function extractDialogResult(eventData)local result,value if type(eventData)=="table" then result=eventData.code value=eventData.message elseif type(eventData)=="number" then result=eventData value=nil else result=UI.DIALOG_EVENT_OK value=eventData end return result,value end local function handleDialogResult(eventData)local currentContext=ContextStack:current()if not currentContext then return end local result,value=extractDialogResult(eventData)if currentContext.type=="newFile" then ContextStack:pop()if result==UI.DIALOG_EVENT_OK and value and value~="" then if value:match("^%s*$")then showBasicAlert(tr("file"),tr("nmfile"),"fileCreateError")else if value:sub(1,1)==" " then value="_"..value:sub(2)end if not value or value=="" or value:match("^%s*$")then showBasicAlert(tr("file"),tr("nmfile"),"fileCreateError")else local success=SYS.newFile(value)if success==SYS.FILE_APP_OK then print("closing menu")if ContextStack:hasContextType("menu")then MenuState:close()end ContextStack:reset("editor",{fileName=value..".txt"})UI.openEditor(value)elseif success==SYS.FILE_APP_FILE_ALREADY_EXISTS then showBasicAlert(tr("file"),tr("fexst"),"fileCreateError")else showBasicAlert(tr("file"),tr("nmfile"),"fileCreateError")end end end elseif result==UI.DIALOG_EVENT_OK then showBasicAlert(tr("file"),tr("nmfile"),"fileCreateError")end elseif currentContext.type=="newProject" then ContextStack:pop()if result==UI.DIALOG_EVENT_OK and value and value~="" then if value:match("^%s*$")then showBasicAlert(tr("proj"),tr("nmprj"),"projectCreateError")else if value:sub(1,1)==" " then value="_"..value:sub(2)end local lowerValue=string.lower(value)if string.find(lowerValue,"^about byok%!")then UI.showAboutBYOKDialog()SYS.delay(DELAY_ABOUT_DIALOG_MS)UI.hideAboutBYOKDialog()if ContextStack:hasContextType("menu")then MenuState:back()end else if ContextStack:hasContextType("editor")then UI.closeEditor()ContextStack:removeContextOfType("editor")end local success=SYS.newProject(value)if success==SYS.FILE_APP_PROJECT_ALREADY_EXISTS then showBasicAlert(tr("proj"),tr("pexst"),"projectCreateError")elseif success~=SYS.FILE_APP_OK then showBasicAlert(tr("proj"),tr("nmprj"),"projectCreateError")else MenuState.current=MENU.MAIN MenuState:show(MENU.FILE)end end end end elseif currentContext.type=="deleteFileConfirm" then ContextStack:pop()if result==UI.DIALOG_EVENT_OK then local deleteFileContext=ContextStack:findContextOfType("deleteFile")if deleteFileContext then local fileName=deleteFileContext.data.value ContextStack:removeAllContextsOfType("deleteFile")local editorContext=ContextStack:findContextOfType("editor")if editorContext and editorContext.data and editorContext.data.fileName==fileName then print("closing editor for deleted file: "..fileName)UI.closeEditor()ContextStack:removeContextOfType("editor")end print("deleting file: "..fileName)local success=SYS.deleteFile(fileName)if success==SYS.FILE_APP_OK then if ContextStack:hasContextType("menu")then MenuState:back()end else showBasicAlert(tr("file"),tr("delfail"),"fileDeleteError")end end else ContextStack:removeAllContextsOfType("deleteFile")end elseif currentContext.type=="wifiPasskey" then ContextStack:pop()if result==UI.DIALOG_EVENT_OK and value and value~="" and currentContext.data then local networkName=currentContext.data.value SYS.connectNewWiFi(networkName,value)ContextStack:push("newWifiConnectionResult")showNotificationWithTimeout(tr("wifi"),tr("conn"),{type="wifiConnecting"},TIMEOUT_CONNECT_MS)end elseif currentContext.type=="syncSetup" then ContextStack:pop()if result==UI.DIALOG_EVENT_OK then SYS.getDeviceToken()end MenuState:show(MENU.MAIN)elseif currentContext.type=="syncDisconnect" then ContextStack:pop()if result==UI.DIALOG_EVENT_OK then SYS.disconnectSync()MenuState:show(MENU.MAIN)end elseif currentContext.type=="editorSearch" then ContextStack:pop()if result==UI.DIALOG_EVENT_OK and value and value~="" then searchState={term=value,termLen=#value,lastMatchPos=-1}UI.requestEditorSearch(value)end elseif currentContext.type=="basicAlert" or currentContext.type=="confirmAlert" or currentContext.type:match("^.*Error$")or(currentContext.data and currentContext.data.alertType)then ContextStack:pop()end end local shutdownInProgress=false local eventHandlers={[EVENT_TYPE.START]=function(mode)if mode==0 then ContextStack:reset()local lastOpenedFileId=SYS.getLastOpenedFileId()if lastOpenedFileId~="" then print("Attempting to restore last opened file: "..lastOpenedFileId)local success=openEditorByFileId(lastOpenedFileId)if success then print("Successfully restored editor with file ID: "..lastOpenedFileId)else print("Failed to restore file with ID: "..lastOpenedFileId..", showing main menu")SYS.setLastOpenedFileId("")ContextStack:push("menu",{menuId=MENU.MAIN})MenuState:show(MENU.MAIN)end else print("No last opened file found, showing main menu")ContextStack:push("menu",{menuId=MENU.MAIN})MenuState:show(MENU.MAIN)end else print("Starting in disk mode")end end,[EVENT_TYPE.SHUTDOWN]=function()shutdownInProgress=true print("Shutdown initiated - blocking further event processing")end,[EVENT_TYPE.MENU_SELECTION]=function(eventData)local handler=menuEventHandlers[eventData]if handler then handler()end end,[EVENT_TYPE.DIALOG_RESULT]=function(eventData)handleDialogResult(eventData)end,[EVENT_TYPE.BT_SCAN_COMPLETE]=function(eventData)hideNotification()local btContext=ContextStack:findContextOfType("btPairing")if btContext then ContextStack:pop()if(eventData>0)then local count=showList(UI.BT_LIST_SCAN)if count==0 then showBasicAlert(tr("bt"),tr("nfd"),"btScanError")end else showBasicAlert(tr("bt"),tr("nfd"),"btScanError")end end end,[EVENT_TYPE.BT_KEYBOARD_CONNECTED]=function(eventData)print("BT Keyboard connected with name: "..eventData)hideNotification()local removedConnectingContexts=ContextStack:removeAllContextsOfType("btConnecting")local removedPairingContexts=ContextStack:removeAllContextsOfType("btPairing")local currentContext=ContextStack:current()if#removedConnectingContexts>0 and(not currentContext or currentContext.type~="editor")then MenuState:show(MENU.MAIN)end end,[EVENT_TYPE.BT_KEYBOARD_DISCONNECTED]=function(eventData)print("BT Keyboard disconnected")end,[EVENT_TYPE.BT_KEYBOARD_PASSKEY]=function(eventData)hideNotification()SYS.delay(DELAY_BT_UI_MS)local pinString=tr("pin")showNotification(tr("bt"),pinString..eventData,{type="btPasskey",passkey=eventData})end,[EVENT_TYPE.BT_KEYBOARD_CONNECTION_FAILED]=function(eventData)hideNotification()SYS.delay(DELAY_BT_UI_MS)showBasicAlert(tr("bt"),tr("nfc"),"btConnectionError")ContextStack:removeAllContextsOfType("btPairing")ContextStack:removeAllContextsOfType("btConnecting")end,[EVENT_TYPE.LIST_ITEM_SELECTED]=function(eventData)local currentContext=ContextStack:current()local success=false local fileName="" if not currentContext or currentContext.type~="list" then return end if not currentContext.data then return end if(eventData==UI.ITEM_BACK)then UI.hideList()ContextStack:pop()if currentContext.data.listType==UI.PROJECT_LIST then ContextStack:removeContextOfType("openProject")elseif currentContext.data.listType==UI.FILE_LIST then if ContextStack:hasContextType("deleteFile")then ContextStack:removeAllContextsOfType("deleteFile")else ContextStack:removeContextOfType("openFile")end end else if currentContext.data.listType==UI.BT_LIST_SCAN or currentContext.data.listType==UI.BT_LIST_KNOWN then SYS.connectBTKeyboard(eventData)UI.hideList()ContextStack:pop()ContextStack:push("btConnecting")showNotificationWithTimeout(tr("bt"),tr("conk"),{type="btConnecting"},TIMEOUT_CONNECT_MS)elseif currentContext.data.listType==UI.WIFI_LIST_KNOWN then local networkName=UI.getListItem(eventData)SYS.connectKnownWifi(networkName)UI.hideList()ContextStack:pop()ContextStack:push("newWifiConnectionResult")showNotificationWithTimeout(tr("wifi"),tr("conn"),{type="wifiConnecting"},TIMEOUT_CONNECT_MS)elseif currentContext.data.listType==UI.WIFI_LIST_SCAN then UI.hideList()ContextStack:pop()local networkName=UI.getListItem(eventData)ContextStack:push("wifiPasskey",{value=networkName})UI.showEntry(tr("wifipass"),"","wifiPasskey")elseif currentContext.data.listType==UI.PROJECT_LIST then UI.hideList()ContextStack:pop()if ContextStack:hasContextType("editor")then UI.closeEditor()ContextStack:removeContextOfType("editor")end local projectName=UI.getListItem(eventData)success=SYS.openProject(projectName)if success==SYS.FILE_APP_OK then ContextStack:removeContextOfType("openProject")MenuState:show(MENU.MAIN)else showBasicAlert(tr("proj"),tr("opfail"),"projectOpenError")end elseif currentContext.data.listType==UI.FILE_LIST then fileName=UI.getListItem(eventData)UI.hideList()ContextStack:pop()if ContextStack:hasContextType("deleteFile")then ContextStack:push("deleteFile",{value=fileName})showConfirmAlert(tr("delf"),fileName:gsub("%.txt$",""),"deleteFileConfirm")else print("Opening file: "..fileName)success=SYS.checkFileGood(fileName)if success==SYS.FILE_APP_OK then ContextStack:removeContextOfType("openFile")if ContextStack:hasContextType("menu")then MenuState:close()end openEditor(fileName)else ContextStack:removeContextOfType("openFile")showBasicAlert(tr("file"),tr("offail"),"fileOpenError")end end elseif currentContext.data.listType==UI.LANGUAGE_LIST then local selectedDisplayName=UI.getListItem(eventData)for code,langData in pairs(Languages)do if langData._displayName==selectedDisplayName then if loadLanguage(code)then Settings.language=code print("Language changed to: "..code.." ("..selectedDisplayName..")")UI.setLanguagePreference(code)else print("Failed to change language to: "..code)end ContextStack:pop()UI.hideList()MenuState:show(MENU.MAIN)break end end elseif currentContext.data.listType==UI.KEYBOARD_LAYOUT_LIST then UI.hideList()ContextStack:pop()SYS.setKeyboardLayout(eventData)elseif currentContext.data.listType==UI.CURSOR_LIST then UI.hideList()ContextStack:pop()UI.setCursorPreference(eventData)end end end,[EVENT_TYPE.FONT_LIST_ITEM_SELECTED]=function(eventData)ContextStack:pop()MenuState:show(MENU.MAIN)end,[EVENT_TYPE.CONTRAST_SET]=function(eventData)ContextStack:pop()end,[EVENT_TYPE.SD_CARD_INSERTED]=function(eventData)if ContextStack:hasContextType("sdCardRemoved")then hideNotification()ContextStack:removeContextOfType("sdCardRemoved")end end,[EVENT_TYPE.SD_CARD_REMOVED]=function(eventData)ContextStack:push("sdCardRemoved")showNotification(tr("sys"),tr("sd"),"sdCardRemoved")end,[EVENT_TYPE.LOW_BATTERY]=function(eventData)showBasicAlert(tr("byok"),tr("low_bat"),"batteryLow")end,[EVENT_TYPE.WIFI_CONNECTION_ENDED]=function(eventData)if ContextStack:hasContextType("newWifiConnectionResult")then ContextStack:removeContextOfType("newWifiConnectionResult")hideNotification()showBasicAlert(tr("sys"),tr("wififail"),"wifiConnectionFailed")end end,[EVENT_TYPE.WIFI_CONNECTION_SUCCESS]=function(eventData)if ContextStack:hasContextType("newWifiConnectionResult")then ContextStack:removeContextOfType("newWifiConnectionResult")hideNotification()SYS.disconnectWiFi()wifiMenu()end end,[EVENT_TYPE.NOTIFICATION_TIMEOUT]=function(eventData)print("Notification timeout occurred - cleaning up silently")local contextType=nil if ContextStack:hasContextType("notification")then local notificationContext=ContextStack:findContextOfType("notification")if notificationContext and notificationContext.data then contextType=notificationContext.data.type print("Notification timeout for context type: "..(contextType or "unknown"))end end hideNotification()if contextType=="btConnecting" or contextType=="btScanning" then ContextStack:removeAllContextsOfType("btPairing")elseif contextType=="wifiConnecting" then ContextStack:removeAllContextsOfType("newWifiConnectionResult")end MenuState:show(MENU.MAIN)end,[EVENT_TYPE.WIFI_CONNECTION_FAILED]=function(eventData)if ContextStack:hasContextType("sync")then local syncCtx=ContextStack:findContextOfType("sync")hideNotification()ContextStack:removeContextOfType("sync")showNotificationWithTimeout(tr("wifi"),tr("wififail"),"syncFailed",TIMEOUT_SYNC_FAILED_MS)tryReopenEditorAfterSync(syncCtx)end end,[EVENT_TYPE.SYNC_FAILED]=function(eventData)local syncCtx=ContextStack:findContextOfType("sync")ContextStack:removeContextOfType("sync")UI.updateNotification(tr("cantsync"))SYS.delay(TIMEOUT_SYNC_FAILED_MS)hideNotification()tryReopenEditorAfterSync(syncCtx)end,[EVENT_TYPE.SYNC_COMPLETED]=function(eventData)hideNotification()local syncCtx=ContextStack:findContextOfType("sync")ContextStack:removeContextOfType("sync")tryReopenEditorAfterSync(syncCtx)end,}function handleGlobalKey(keyInfo)currentKeyInfo=keyInfo local keycode=keyInfo.keycode or 0 if keyInfo.is_control then if keycode==0x00 then keycode=KEY_CTRL_SPACE end local handler=keyHandlers[keycode]if handler then return handler()end end if keyInfo.type=="function" then print("function key")elseif keyInfo.type=="navigation" then print("navigation key")end return false end function handleButton(button)local currentContext=ContextStack:current()if currentContext and currentContext.type=="editor" then if button=="execute" then if not ContextStack:hasContextType("menu")then MenuState:show(MENU.MAIN)return true end end end return false end function tr(key)if CurrentLanguage and CurrentLanguage[key]then return CurrentLanguage[key]end return key end function PrintContext()local context=ContextStack:current()if context then print("Current context: "..context.type)for k,v in pairs(context.data or{})do print(" "..k..": "..tostring(v))end else print("No active context")end end function handleEvent(eventType,eventData)if shutdownInProgress and eventType~=EVENT_TYPE.SHUTDOWN then print("Ignoring event "..eventType.." - shutdown in progress")return end local handler=eventHandlers[eventType]if handler then handler(eventData)end end print("system init'd, waiting for start")