Advertisement
Guest User

Untitled

a guest
Apr 4th, 2020
763
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 101.64 KB | None | 0 0
  1. if (File.exists("c.lua")) then File.delete("c.lua"); end
  2.  
  3. local scrSize = Vector2(guiGetScreenSize());
  4. cursorPosition = Vector2();
  5. isCursorShown = false;
  6.  
  7. local HISTORY_CALL_TYPE = {INCOMING = 0, INCOMING_UNANSWERED = 1, OUTGOING = 2};
  8. local HISOTRY_CALL_TYPE_TEXTS = {
  9.     [HISTORY_CALL_TYPE.INCOMING]            = "Bejövő",
  10.     [HISTORY_CALL_TYPE.INCOMING_UNANSWERED] = "#D63131Nem fogadott#646464",
  11.     [HISTORY_CALL_TYPE.OUTGOING]            = "Kimenő",
  12. }
  13.  
  14. local CALL_STATE = {
  15.     CALLING = 0,
  16.     TALKING = 1,
  17.     CALLED_NUMBER_UNAVAILABLE = 2,
  18.     INVALID_NUMBER = 3,
  19.     LINE_BUSY = 4,
  20.     ITEM_OWNER_NOT_PLAYER = 5,
  21.     TIMEOUT = 6,
  22.     ENDED = 7,
  23.     CONNECTION_LOST = 8
  24. };
  25.  
  26. local CALL_STATE_TEXTS = {
  27.     [CALL_STATE.CALLING]                    = {"Tárcsázás..", "Bejövő hívás"},
  28.     [CALL_STATE.TALKING]                    = "Beszélgetés..",
  29.     [CALL_STATE.CALLED_NUMBER_UNAVAILABLE]  = "A hívott szám nem elérhető",
  30.     [CALL_STATE.INVALID_NUMBER]             = "Helytelen szám",
  31.     [CALL_STATE.LINE_BUSY]                  = "Foglalt",
  32.     [CALL_STATE.ITEM_OWNER_NOT_PLAYER]      = "Kicsörgött",
  33.     [CALL_STATE.TIMEOUT]                    = "Timeout",
  34.     [CALL_STATE.ENDED]                      = "Beszélgetés befejezve",
  35.     [CALL_STATE.CONNECTION_LOST]            = "Kapcsolat megszakadt"
  36. };
  37.  
  38. local WEEKDAY_NAMES = {[0] = "Hétfő", "Kedd", "Szerda", "Csütörtök", "Péntek", "Szombat", "Vasárnap"};
  39. local MONTH_NAMES = {[0] = "Jan.", "Feb.", "Márc.", "Ápr.", "Máj.", "Jún.", "Júl.", "Aug.", "Szep.", "Okt.", "Nov.", "Dec."};
  40.  
  41. local responsiveMultiplier = Vector2(reMap(scrSize.y, 768, 1080, 0.7, 1), reMap(scrSize.y, 768, 1080, 0.7, 1));
  42.  
  43. fonts = {
  44.     roboto_light = {
  45.         [26] = DxFont("files/fonts/Roboto-Light.ttf", 26 * responsiveMultiplier.x, false, "cleartype"),
  46.         [18] = DxFont("files/fonts/Roboto-Light.ttf", 18 * responsiveMultiplier.x, false, "cleartype"),
  47.         [16] = DxFont("files/fonts/Roboto-Light.ttf", 16 * responsiveMultiplier.x, false, "cleartype"),
  48.         [14] = DxFont("files/fonts/Roboto-Light.ttf", 14 * responsiveMultiplier.x, false, "cleartype"),
  49.         [12] = DxFont("files/fonts/Roboto-Light.ttf", 12 * responsiveMultiplier.x, false, "cleartype"),
  50.         [10] = DxFont("files/fonts/Roboto-Light.ttf", 10 * responsiveMultiplier.x, false, "cleartype")
  51.     },
  52.     roboto_regular = {
  53.         [18] = DxFont("files/fonts/Roboto-Regular.ttf", 18 * responsiveMultiplier.x, false, "cleartype"),
  54.         [16] = DxFont("files/fonts/Roboto-Regular.ttf", 16 * responsiveMultiplier.x, false, "cleartype"),
  55.         [14] = DxFont("files/fonts/Roboto-Regular.ttf", 14 * responsiveMultiplier.x, false, "cleartype"),
  56.         [12] = DxFont("files/fonts/Roboto-Regular.ttf", 12 * responsiveMultiplier.x, false, "cleartype"),
  57.         [10] = DxFont("files/fonts/Roboto-Regular.ttf", 10 * responsiveMultiplier.x, false, "cleartype")
  58.     },
  59.     roboto_medium = {
  60.         [24] = DxFont("files/fonts/Roboto-Medium.ttf", 24 * responsiveMultiplier.x, false, "cleartype"),
  61.         [18] = DxFont("files/fonts/Roboto-Medium.ttf", 18 * responsiveMultiplier.x, false, "cleartype"),
  62.         [16] = DxFont("files/fonts/Roboto-Medium.ttf", 16 * responsiveMultiplier.x, false, "cleartype"),
  63.         [14] = DxFont("files/fonts/Roboto-Medium.ttf", 14 * responsiveMultiplier.x, false, "cleartype"),
  64.         [12] = DxFont("files/fonts/Roboto-Medium.ttf", 12 * responsiveMultiplier.x, false, "cleartype"),
  65.         [10] = DxFont("files/fonts/Roboto-Medium.ttf", 10 * responsiveMultiplier.x, false, "cleartype")
  66.     }
  67. };
  68.  
  69. local callInfo = {}
  70. local lastPanelID, currentPanelID;
  71.  
  72. local PANEL = {
  73.     MENU = 0,
  74.     ADVERTISING = 1,
  75.     CONTACTS = 2,
  76.     BALANCE = 3,
  77.     CAMERA = 4,
  78.     GALLERY = 5,
  79.     SETTINGS = 6,
  80.     CALENDAR = 7,
  81.     CLOCK = 8,
  82.     COMPASS = 10,
  83.     MESSAGES = 11,
  84.     MUSIC = 12,
  85.     FILES = 23,
  86.     EDIT_CONTACT = 13,
  87.  
  88.     CALL_CHAT = 14,
  89.     CALL_OUTGOING = 15,
  90.     CALL_INCOMING = 16,
  91.     CALL_HISTORY = 17,
  92.     CALL_KEYPAD = 18,
  93.  
  94.     CONTACT_MESSENGER = 19,
  95.     CONTACT_ADD_OR_EDIT = 20, -- add if panels[PANEL.CONTACT_ADD_OR_EDIT].edit == nil, otherwise edit
  96.     CONTACT_FAVORITES = 21,
  97.  
  98.     WALLPAPER_CHANGE = 22
  99.  
  100. };
  101.  
  102. local soundElementsByPhone = setmetatable({}, CREATE_INDEX_IF_NIL_MT1D); -- key: phoneNumber, value: {ringtone = <elem>, sms = <elem>}. Desc: Contains the current ringtone / sms element of the given phone.
  103.  
  104. local isShowing = false;
  105.  
  106. local phoneData = {wallpaperID = 0};
  107.  
  108. local position = Vector2(500, 200) * responsiveMultiplier;
  109. local screenPosition = position + Vector2(18, 18) * responsiveMultiplier; -- the positions picture are drawn at, so the border can overlap them
  110.  
  111. -- Size must be a fixed one, otherwise things blow up.
  112. local size = Vector2(328, 638) * responsiveMultiplier;
  113. local screenSize = size - Vector2(2 * 18, 2 * 18) * responsiveMultiplier;
  114.  
  115. local panels = {}; -- panel renderes
  116.  
  117. local panelSetHistory = {};
  118.  
  119. function setPhoneVisible(newState, newPhoneData)
  120.     if (newState == isShowing) then return; end
  121.     isShowing = newState;
  122.  
  123.     if (newState) then
  124.         panelSetHistory = {};
  125.     end
  126.  
  127.     if (newPhoneData) then
  128.         phoneData = newPhoneData;
  129.  
  130.         local contacts = phoneData.contacts;
  131.         phoneData.favoriteContacts = {};
  132.         phoneData.contacts = {};
  133.         for _, v in pairs(contacts) do
  134.             if (v.favorite) then table.insert(phoneData.favoriteContacts, contact); end
  135.             table.insert(phoneData.contacts, v);
  136.         end
  137.        
  138.         sortContactList();
  139.  
  140.         local oldMessages = phoneData.messages;
  141.         phoneData.messages = {};
  142.         for number, v in pairs(oldMessages) do
  143.             table.insert(phoneData.messages, v);
  144.             phoneData.messages[#phoneData.messages].number = number;
  145.         end
  146.  
  147.         sortSMSArray();
  148.  
  149.         if (not File.exists("files/textures/wallpapers/" .. phoneData.settings.wallpaper  .. ".png")) then
  150.             phoneData.settings.wallpaper = 0;
  151.         end
  152.     end
  153.  
  154.     setCurrentPanel(PANEL.MENU);
  155.  
  156.  
  157.     local eventHandlerRemoveAdd = newState and addEventHandler or removeEventHandler;
  158.     eventHandlerRemoveAdd("onClientRender", root, onClientRender, false, "low-100");
  159.     eventHandlerRemoveAdd("onClientClick", root, onClientClick);
  160.  
  161.     local bindOrUnbind = newState and bindKey or unbindKey;
  162.     bindOrUnbind("backspace", "down", goBackToPanelCameFrom);
  163. end
  164.  
  165. function setCurrentPanel(panelID)
  166.     if (not panels[panelID]) then return; end
  167.  
  168.     if (panelID == PANEL.CAMERA and localPlayer.vehicle) then exports.cr_infobox:addBox("warning", "Kocsiban nem használhatod a fényképezőt."); return; end
  169.  
  170.     lastPanelID = currentPanelID;
  171.     currentPanelID = panelID;
  172.  
  173.     outputChatBox("switch panel from " .. tostring(lastPanelID) .. " to " .. tostring(currentPanelID));
  174.  
  175.     if (lastPanelID) then
  176.         if (lastPanelID ~= PANEL.CALL_INCOMING and lastPanelID ~= PANEL.CALL_OUTGOING and lastPanelID ~= PANEL.CALL_CHAT) then
  177.             table.insert(panelSetHistory, lastPanelID);
  178.         end
  179.  
  180.         if (lastPanelID == PANEL.SETTINGS and currentPanelID ~= PANEL.WALLPAPER_CHANGE) then
  181.             triggerServerEvent("onClientPlayerChangePhoneSettings", localPlayer, phoneData.settings);
  182.         end
  183.  
  184.         if (panels[lastPanelID].deinit) then panels[lastPanelID].deinit(); end
  185.     end
  186.     if (panels[currentPanelID].init) then panels[currentPanelID].init(); end
  187. end
  188.  
  189. function onClientRender()
  190.     isCursorShown = isCursorShowing()
  191.     if (isCursorShown) then
  192.         cursorPosition = Vector2(getCursorPosition()) * scrSize;
  193.     end
  194.    
  195.     dxDrawText(inspect(panelSetHistory), 650, 120)
  196.  
  197.     if (currentPanelID == PANEL.CAMERA) then
  198.         dxDrawRectangle(scrSize / 2 - Vector2(screenSize.y, screenSize.x) / 2, screenSize.y, screenSize.x, 0xFF2c2c2c);
  199.     else
  200.         dxDrawRectangle(screenPosition, screenSize, 0xFF000000);
  201.     end
  202.     if (panels[currentPanelID].render) then panels[currentPanelID].render(); end
  203.  
  204.     if (currentPanelID == PANEL.CAMERA) then
  205.         dxDrawImage(scrSize / 2 - Vector2(size.y, size.x) / 2, size.y, size.x, "files/textures/iphonex90.png");
  206.     else
  207.         dxDrawImage(position, size, "files/textures/iphonex.png");
  208.     end
  209. end
  210.  
  211. function onClientClick(button, state, x, y)
  212.     if (not wasEventCancelled() and panels[currentPanelID].click) then
  213.         panels[currentPanelID].click(button, state == "down", Vector2(x, y));
  214.     end
  215. end
  216.  
  217. panels[PANEL.MENU] = {
  218.     init = function()
  219.  
  220.     end,
  221.  
  222.     render = function()
  223.         dxDrawImage(screenPosition, screenSize, "files/textures/wallpapers/" .. phoneData.settings.wallpaper .. ".png");
  224.  
  225.         local iconMarginRight = screenSize.x * 0.06;
  226.         local iconSize = (screenSize.x - iconMarginRight) / 4 - iconMarginRight;
  227.        
  228.         local icons = {
  229.             "files/textures/icons/menu/balance.png",
  230.             "files/textures/icons/menu/calendar.png",
  231.             "files/textures/icons/menu/camera.png",
  232.             "files/textures/icons/menu/clock.png",
  233.             "files/textures/icons/menu/compass.png",
  234.             "files/textures/icons/menu/files.png",
  235.             "files/textures/icons/menu/music.png",
  236.             "files/textures/icons/menu/settings.png",
  237.         };
  238.  
  239.         local i = 0;
  240.         for y = screenPosition.y + screenSize.y * 0.1, screenPosition.y + screenSize.y * 0.22, screenSize.y * 0.12 do
  241.             for x = screenPosition.x + iconMarginRight, screenPosition.x + screenSize.x, iconSize + iconMarginRight do
  242.                 dxDrawImage(x, y, iconSize, iconSize, icons[i + 1]);
  243.  
  244.                 i = i + 1;
  245.                 if (i % 4 == 0) then break; end
  246.             end
  247.         end
  248.  
  249.         -- 266, 68
  250.         local dockerPadding = screenSize.x * 0.045;
  251.         local iconMarginRight = screenSize.x * 0.0766;
  252.         local dockerMargin = dockerPadding;
  253.  
  254.         local iconSize = (screenSize.x - 1 * dockerPadding - 2 * dockerMargin) / 4 - iconMarginRight;
  255.        
  256.         dxDrawImage(screenPosition.x + dockerMargin, screenPosition.y + screenSize.y - dockerMargin - dockerPadding - iconSize - dockerPadding,
  257.                     screenSize.x - 2 * dockerMargin, iconSize + 2 * dockerPadding, "files/textures/docker_bg.png");
  258.  
  259.         local icons = {
  260.             "files/textures/icons/menu/messages.png",
  261.             "files/textures/icons/menu/contacts.png",
  262.             "files/textures/icons/menu/ad.png",
  263.             "files/textures/icons/menu/call.png",
  264.         };
  265.         local i = 1;
  266.         for x = screenPosition.x + dockerMargin + dockerPadding, screenPosition.x + screenSize.x - dockerMargin - dockerPadding, iconSize + iconMarginRight do
  267.             dxDrawImage(x, screenPosition.y + screenSize.y - dockerMargin - dockerPadding - iconSize, iconSize, iconSize, icons[i]);
  268.             i = i + 1;
  269.         end
  270.     end,
  271.  
  272.     click = function(button, state, position)
  273.         if (button ~= "left" or (not state)) then return; end
  274.  
  275.         local iconMarginRight = screenSize.x * 0.06;
  276.         local iconSize = (screenSize.x - iconMarginRight) / 4 - iconMarginRight;
  277.        
  278.         local i = 0;
  279.         for y = screenPosition.y + screenSize.y * 0.1, screenPosition.y + screenSize.y * 0.22, screenSize.y * 0.12 do
  280.             for x = screenPosition.x + iconMarginRight, screenPosition.x + screenSize.x, iconSize + iconMarginRight do
  281.                 if (isCursorOnRectangle(x, y, iconSize, iconSize)) then
  282.                     setCurrentPanel(({PANEL.BALANCE, PANEL.CALENDAR, PANEL.CAMERA, PANEL.CLOCK, PANEL.COMPASS, PANEL.FILES, PANEL.MUSIC, PANEL.SETTINGS})[i + 1]);
  283.  
  284.                     return;
  285.                 end
  286.  
  287.                 i = i + 1;
  288.                 if (i % 4 == 0) then break; end
  289.             end
  290.         end
  291.  
  292.         -- 266, 68
  293.         local dockerPadding = screenSize.x * 0.045;
  294.         local iconMarginRight = screenSize.x * 0.0766;
  295.         local dockerMargin = dockerPadding;
  296.  
  297.         local iconSize = (screenSize.x - 1 * dockerPadding - 2 * dockerMargin) / 4 - iconMarginRight;
  298.        
  299.         local i = 1;
  300.         for x = screenPosition.x + dockerMargin + dockerPadding, screenPosition.x + screenSize.x - dockerMargin - dockerPadding, iconSize + iconMarginRight do
  301.             if (isCursorOnRectangle(x, screenPosition.y + screenSize.y - dockerMargin - dockerPadding - iconSize, iconSize, iconSize)) then
  302.                 setCurrentPanel(({PANEL.MESSAGES, PANEL.CONTACTS, PANEL.ADVERTISING, PANEL.CALL_KEYPAD})[i]);
  303.  
  304.                 return;
  305.             end
  306.             i = i + 1;
  307.  
  308.         end
  309.  
  310.     end
  311. }
  312.  
  313. panels[PANEL.BALANCE] = {
  314.     render = function()
  315.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  316.  
  317.         -- back button
  318.         dxDrawImage(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15, "files/textures/icons/arrow_left.png");
  319.  
  320.         dxDrawText("Egyenlegem", screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  321.  
  322.         -- sep. line
  323.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.23, screenSize.x, 2, 0x80464646);
  324.  
  325.         local fontHeight = dxGetFontHeight(1, fonts.roboto_medium[12]);
  326.  
  327.         dxDrawText("Szolgáltató: ", screenPosition.x + 15, screenPosition.y + screenSize.y * 0.32, screenPosition.x + screenSize.x - 15, 0, tocolor(128, 128, 128), 1, fonts.roboto_regular[14], "left", "top")
  328.         dxDrawText("Telecom", screenPosition.x + 15, screenPosition.y + screenSize.y * 0.32, screenPosition.x + screenSize.x - 15, 0, tocolor(128, 128, 128), 1, fonts.roboto_light[14], "right", "top")
  329.         dxDrawRectangle(screenPosition.x + 15, screenPosition.y + screenSize.y * 0.32 + fontHeight + 2, screenSize.x - 30, 1, tocolor(128, 128, 128), false, false);
  330.  
  331.         dxDrawText("Telefonszámom: ", screenPosition.x + 15, screenPosition.y + screenSize.y * 0.39, screenPosition.x + screenSize.x - 15, 0, tocolor(128, 128, 128), 1, fonts.roboto_regular[14], "left", "top")
  332.         dxDrawText(phoneData.number, screenPosition.x + 15, screenPosition.y + screenSize.y * 0.39, screenPosition.x + screenSize.x - 15, 0, tocolor(128, 128, 128), 1, fonts.roboto_light[14], "right", "top")
  333.         dxDrawRectangle(screenPosition.x + 15, screenPosition.y + screenSize.y * 0.39 + fontHeight + 2, screenSize.x - 30, 1, tocolor(128, 128, 128), false, false);
  334.  
  335.  
  336.         dxDrawText("Egyenlegem: ", screenPosition.x + 15, screenPosition.y + screenSize.y * 0.46, screenPosition.x + screenSize.x - 15, 0, tocolor(128, 128, 128), 1, fonts.roboto_regular[14], "left", "top")
  337.         dxDrawText(phoneData.balance, screenPosition.x + 15, screenPosition.y + screenSize.y * 0.46, screenPosition.x + screenSize.x - 15, 0, tocolor(128, 128, 128), 1, fonts.roboto_light[14], "right", "top")
  338.         dxDrawRectangle(screenPosition.x + 15, screenPosition.y + screenSize.y * 0.46 + fontHeight + 2, screenSize.x - 30, 1, tocolor(128, 128, 128), false, false);
  339.  
  340.     end,
  341.  
  342.     click = function(button, state, position)
  343.         if (button ~= "left" or (not state)) then return; end
  344.  
  345.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15)) then
  346.             setCurrentPanel(PANEL.MENU);
  347.         end
  348.     end,
  349. }
  350.  
  351. panels[PANEL.CONTACT_ADD_OR_EDIT] = {
  352.     init = function()
  353.         local thisPanel = panels[PANEL.CONTACT_ADD_OR_EDIT];
  354.         thisPanel.nameEditBox = GuiEdit(-1000, -1000, 0, 0, "", false);
  355.         thisPanel.nameEditBox.maxLength = 16;
  356.  
  357.         thisPanel.numberEditBox = GuiEdit(-1000, -1000, 0, 0, "", false);
  358.         thisPanel.numberEditBox.maxLength = 10;
  359.  
  360.         if (thisPanel.editedContact) then
  361.             thisPanel.nameEditBox:setText(thisPanel.editedContact.name);
  362.             thisPanel.numberEditBox:setText(thisPanel.editedContact.number);
  363.             thisPanel.title = "Szerkesztés";
  364.         else
  365.             thisPanel.title = "Hozzáadás";
  366.  
  367.         end
  368.     end,
  369.  
  370.     deinit = function()
  371.         local thisPanel = panels[PANEL.CONTACT_ADD_OR_EDIT];
  372.         thisPanel.nameEditBox:destroy();
  373.         thisPanel.numberEditBox:destroy();
  374.     end,
  375.  
  376.     render = function()
  377.         local thisPanel = panels[PANEL.CONTACT_ADD_OR_EDIT];
  378.  
  379.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  380.  
  381.         -- back button
  382.         dxDrawImage(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15, "files/textures/icons/arrow_left.png");
  383.  
  384.         if (thisPanel.editedContact) then
  385.             dxDrawImage(screenPosition.x + screenSize.x * 0.88, screenPosition.y + screenSize.y * 0.23 / 2 - 12 / 2, 12, 12, "files/textures/icons/accept.png");
  386.         else
  387.             dxDrawImage(screenPosition.x + screenSize.x * 0.88, screenPosition.y + screenSize.y * 0.23 / 2 - 12 / 2, 12, 12, "files/textures/icons/add.png");
  388.         end
  389.  
  390.         dxDrawText(thisPanel.title, screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  391.  
  392.         -- sep. line
  393.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.23, screenSize.x, 2, 0x80464646);
  394.  
  395.         local fontHeight = dxGetFontHeight(1, fonts.roboto_medium[12]);
  396.  
  397.         dxDrawText("Név: ", screenPosition.x + 15, screenPosition.y + screenSize.y * 0.32, screenPosition.x + screenSize.x - 15, 0, 0xFF464646, 1, fonts.roboto_medium[16], "left", "top")
  398.         dxDrawText(thisPanel.nameEditBox:getText(), screenPosition.x + 15, screenPosition.y + screenSize.y * 0.32, screenPosition.x + screenSize.x - 15, 0, 0xFF464646, 1, fonts.roboto_light[16], "right", "top")
  399.         dxDrawRectangle(screenPosition.x + 15, screenPosition.y + screenSize.y * 0.32 + fontHeight + 2, screenSize.x - 30, 1, 0xFF464646, false, false);
  400.  
  401.         dxDrawText("Telefonszám: ", screenPosition.x + 15, screenPosition.y + screenSize.y * 0.39, screenPosition.x + screenSize.x - 15, 0, 0xFF464646, 1, fonts.roboto_medium[16], "left", "top")
  402.         dxDrawText(thisPanel.numberEditBox:getText(), screenPosition.x + 15, screenPosition.y + screenSize.y * 0.39, screenPosition.x + screenSize.x - 15, 0, 0xFF464646, 1, fonts.roboto_light[16], "right", "top")
  403.         dxDrawRectangle(screenPosition.x + 15, screenPosition.y + screenSize.y * 0.39 + fontHeight + 2, screenSize.x - 30, 1, 0xFF464646, false, false);
  404.     end,
  405.  
  406.     click = function(button, state, position)
  407.         if (button ~= "left" or (not state)) then return; end
  408.         local thisPanel = panels[PANEL.CONTACT_ADD_OR_EDIT];
  409.  
  410.         local fontHeight = dxGetFontHeight(1, fonts.roboto_medium[14]);
  411.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15)) then
  412.             goBackToPanelCameFrom();
  413.  
  414.         elseif (isCursorOnRectangle(screenPosition.x + 15, screenPosition.y + screenSize.y * 0.32, screenSize.x - 30, fontHeight)) then -- focus name field
  415.             thisPanel.nameEditBox:bringToFront();
  416.             thisPanel.nameEditBox:setCaretIndex(#thisPanel.nameEditBox:getText());
  417.  
  418.         elseif (isCursorOnRectangle(screenPosition.x + 15, screenPosition.y + screenSize.y * 0.39, screenSize.x - 30, fontHeight)) then -- focus number field
  419.             thisPanel.numberEditBox:bringToFront();
  420.             thisPanel.numberEditBox:setCaretIndex(#thisPanel.numberEditBox:getText());
  421.  
  422.         elseif (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.88, screenPosition.y + screenSize.y * 0.23 / 2 - 12 / 2, 12, 12)) then -- add / edit
  423.             local name, number = thisPanel.nameEditBox:getText(), tonumber(thisPanel.numberEditBox:getText());
  424.                
  425.             if (#name == 0) then exports['cr_infobox']:addBox("error", "A név legalább 1 karakter hosszú kell, hogy legyen"); return; end
  426.             if (not checkIfNumberIsValidAndAlertIfNot(tostring(number))) then return; end
  427.            
  428.             local sameContact = getContactFromNumber(number);
  429.             if (sameContact and sameContact ~= thisPanel.editedContact) then
  430.                 exports['cr_infobox']:addBox("error", "Ez a telefonszám már szerepel a kacspolatok között");
  431.                 return;
  432.             end
  433.    
  434.             local sameContact = getContactFromName(name);
  435.             if (sameContact and sameContact ~= thisPanel.editedContact) then
  436.                 exports['cr_infobox']:addBox("error", "Ez a név már szerepel a kacspolatok között");
  437.                 return;
  438.             end
  439.  
  440.             if (thisPanel.editedContact) then -- edit
  441.                 triggerServerEvent("onPlayerEditPhoneContact", localPlayer, thisPanel.editedContact.id, name, number);
  442.                 thisPanel.editedContact.name = name;
  443.                 thisPanel.editedContact.number = number;
  444.                 thisPanel.editedContact = nil;
  445.                
  446.                 goBackToPanelCameFrom();
  447.             else -- add
  448.                 triggerServerEvent("onPlayerAddPhoneContact", localPlayer, name, number);
  449.                 goBackToPanelCameFrom();
  450.             end    
  451.         end
  452.     end,
  453. }
  454.  
  455. --[[ panels[PANEL.MUSIC] = {
  456.     render = function()
  457.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  458.  
  459.         -- back button
  460.         dxDrawImage(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15, "files/textures/icons/arrow_left.png");
  461.  
  462.        
  463.         dxDrawText("Rádió", screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  464.  
  465.         -- sep. line
  466.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.23, screenSize.x, 2, 0x80464646);
  467.  
  468.  
  469.         -- todo
  470.     end,
  471.  
  472.     click = function(button, state, position)
  473.         if (button ~= "left" or (not state)) then return; end
  474.  
  475.  
  476.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15)) then
  477.             setCurrentPanel(PANEL.MENU);
  478.         end
  479.     end
  480. } ]]
  481.  
  482. panels[PANEL.ADVERTISING] = {
  483.     init = function()
  484.         panels[PANEL.ADVERTISING].editbox:setMaxLength(120);
  485.  
  486.         bindKey("enter", "down", panels[PANEL.ADVERTISING].sendAd);
  487.         bindKey("num_enter", "down", panels[PANEL.ADVERTISING].sendAd);
  488.     end,
  489.  
  490.     deinit = function()
  491.         unbindKey("enter", "down", panels[PANEL.ADVERTISING].sendAd);
  492.         unbindKey("num_enter", "down", panels[PANEL.ADVERTISING].sendAd);
  493.     end,
  494.  
  495.     render = function()
  496.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  497.  
  498.         -- back button
  499.         dxDrawImage(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15, "files/textures/icons/arrow_left.png");
  500.  
  501.    
  502.         dxDrawText("Hirdetés feladás", screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  503.  
  504.         -- sep. line
  505.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.23, screenSize.x, 2, 0x80464646);
  506.  
  507.         local boxWidth = screenSize.x * 0.84;
  508.         local boxContectWidth = screenSize.x * 0.675;
  509.  
  510.         local charWidth = dxGetTextWidth("0123456789", 1, fonts.roboto_light[14]) / 10;      
  511.         local lineCount = (charWidth * panels[PANEL.ADVERTISING].editbox.maxLength) / boxContectWidth;
  512.  
  513.         local boxHeight = lineCount * dxGetFontHeight(1, fonts.roboto_light[14]) + 20;
  514.  
  515.  
  516.         dxDrawRectangle(screenPosition + Vector2(screenSize.x * 0.088 - 2, screenSize.y - 20 - boxHeight - 2), boxWidth + 4, boxHeight + 4, 0x80464646);
  517.         dxDrawRectangle(screenPosition + Vector2(screenSize.x * 0.088, screenSize.y - 20 - boxHeight), boxWidth, boxHeight, 0xFFFFFFFF);
  518.  
  519.         dxDrawText(panels[PANEL.ADVERTISING].editbox:getText(), screenPosition + Vector2(screenSize.x * 0.088 + 2, screenSize.y - 18 - boxHeight), screenPosition + Vector2(screenSize.x * 0.088 + boxContectWidth, screenSize.y - 34), 0xFF464646, 1, fonts.roboto_light[14], "left", "top", true, true)
  520.    
  521.         dxDrawImage(screenPosition + Vector2(screenSize.x * 0.088 + boxWidth - 30, screenSize.y - 50), 25, 25, "files/textures/icons/send.png");
  522.  
  523.         -- check box
  524.         dxDrawRectangle(screenPosition + Vector2(screenSize.x * 0.088 - 1, screenSize.y - 20 - boxHeight - 21), 12, 12, 0x80464646); --bg
  525.         dxDrawRectangle(screenPosition + Vector2(screenSize.x * 0.088, screenSize.y - 20 - boxHeight - 20), 10, 10, panels[PANEL.ADVERTISING].hidePhoneNumber and 0x80464646 or 0xFFFFFFFF); --bg
  526.         dxDrawText("Telefonszám elrejtése", screenPosition + Vector2(screenSize.x * 0.088 + 14, screenSize.y - 20 - boxHeight - 21), 0, 0, 0xFF464646, 1, fonts.roboto_light[14], "left", "top");
  527.     end,
  528.  
  529.     sendAd = function()
  530.         local thisPanel = panels[PANEL.ADVERTISING];
  531.  
  532.         local text = thisPanel.editbox:getText();
  533.         if (#text < 10) then exports['cr_infobox']:addBox("error", "A hírdetés leírása legalább 10 karakter hosszú kell, hogy legyen"); return; end
  534.         triggerServerEvent("onClientPlayerSendAdvertisement", localPlayer, thisPanel.editbox:getText(), thisPanel.hidePhoneNumber);
  535.     end,
  536.  
  537.     click = function(button, state, position)
  538.         if (button ~= "left" or (not state)) then return; end
  539.         local thisPanel = panels[PANEL.ADVERTISING];
  540.  
  541.         local boxWidth = screenSize.x * 0.84;
  542.         local boxContectWidth = screenSize.x * 0.675;
  543.  
  544.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15)) then -- back button
  545.             goBackToPanelCameFrom();
  546.        
  547.         elseif (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.088 + boxWidth - 30,  screenPosition.y + screenSize.y - 50, 25, 25)) then -- send ad
  548.             thisPanel.sendAd();
  549.  
  550.         else  
  551.             local charWidth = dxGetTextWidth("0123456789abcdefg", 1, fonts.roboto_light[14]) / #("0123456789abcdefg");      
  552.             local lineCount = (charWidth * thisPanel.editbox.maxLength) / boxContectWidth;    
  553.             local boxHeight = lineCount * dxGetFontHeight(1, fonts.roboto_light[14]) + 20;
  554.  
  555.             if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.088, screenPosition.y + screenSize.y - 20 - boxHeight - 21, 12, 12)) then -- hide phone number checkbox
  556.                 thisPanel.hidePhoneNumber = not thisPanel.hidePhoneNumber;
  557.  
  558.             elseif (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.088, screenPosition.y + screenSize.y - 20 - boxHeight, boxWidth, boxHeight)) then -- focus to editbox
  559.                 thisPanel.editbox:bringToFront();
  560.                 thisPanel.editbox:setCaretIndex(#thisPanel.editbox:getText());
  561.             end
  562.         end
  563.     end,
  564.  
  565.     hidePhoneNumber = false,
  566.     editbox = GuiEdit(-1000, -1000, 0, 0, "", false)
  567. }
  568.  
  569. panels[PANEL.CONTACTS] = {
  570.     init = function()
  571.         local this = panels[PANEL.CONTACTS];
  572.  
  573.         local height = screenSize.y * 0.65;
  574.         this.drawableContactCount = math.floor(height / (screenSize.y * 0.08));
  575.         this.contactHeight = height / this.drawableContactCount;
  576.  
  577.         bindKey("mouse_wheel_up", "down", this.scrollHandler);
  578.         bindKey("mouse_wheel_down", "down", this.scrollHandler);
  579.     end,
  580.  
  581.     deinit = function()
  582.         local this = panels[PANEL.CONTACTS];
  583.         unbindKey("mouse_wheel_up", "down", this.scrollHandler);
  584.         unbindKey("mouse_wheel_down", "down", this.scrollHandler);
  585.     end,
  586.  
  587.     scrollHandler = function(key)
  588.         if (not isCursorOnRectangle(screenPosition.x, screenPosition.y, screenSize.x, screenSize.y)) then return; end
  589.  
  590.         local this = panels[PANEL.CONTACTS];
  591.  
  592.         if (key == "mouse_wheel_down" and (this.scrollIndex + 1 + this.drawableContactCount < #phoneData.contacts)) then
  593.             this.scrollIndex = this.scrollIndex + 1;
  594.         elseif (key == "mouse_wheel_up" and (this.scrollIndex - 1 >= 0)) then
  595.             this.scrollIndex = this.scrollIndex - 1;
  596.         end
  597.     end,
  598.  
  599.     render = function()
  600.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  601.  
  602.         -- back button
  603.         dxDrawImage(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15, "files/textures/icons/arrow_left.png");
  604.         dxDrawImage(screenPosition.x + screenSize.x * 0.88, screenPosition.y + screenSize.y * 0.23 / 2 - 12 / 2, 12, 12, "files/textures/icons/add.png");
  605.        
  606.         dxDrawText("Kapcsolatok", screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  607.  
  608.         -- sep. line
  609.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.16, screenSize.x, 1, 0x80464646);
  610.  
  611.         drawContactTabBar();
  612.  
  613.         local y = screenPosition.y + screenSize.y * 0.162;
  614.         local h = panels[PANEL.CONTACTS].contactHeight
  615.         for i = panels[PANEL.CONTACTS].scrollIndex, panels[PANEL.CONTACTS].scrollIndex + panels[PANEL.CONTACTS].drawableContactCount do
  616.             local v = phoneData.contacts[i + 1];
  617.             if (not v) then break; end
  618.  
  619.             local clipX = screenPosition.x + screenSize.x * 0.925;
  620.             if (isCursorOnRectangle(screenPosition.x, y, screenSize.x, h)) then
  621.                 local actionSize = screenSize * Vector2(0.3, 0.026);
  622.                 dxDrawImage(screenPosition.x + screenSize.x * 0.936 - actionSize.x - actionSize.x / 4, y + h / 2 - actionSize.y / 2, screenSize.x * 0.042, actionSize.y, "files/textures/icons/contact_app/favorites.png", 0, 0, 0, v.favorite and 0xFFFFD700 or 0xFFFFFFFF);
  623.                 dxDrawImage(screenPosition.x + screenSize.x * 0.936 - actionSize.x, y + h / 2 - actionSize.y / 2, actionSize, "files/textures/icons/contact_app/actions.png");
  624.  
  625.                 clipX = screenPosition.x + screenSize.x * 0.936 - actionSize.x - actionSize.x / 4 - 5;
  626.             end
  627.  
  628.             dxDrawImage(screenPosition.x + screenSize.x * 0.062, y + 3, h - 6, h - 6, "files/textures/profile_pics/" .. v.profilePictureID .. ".png");
  629.             dxDrawText(v.name, screenPosition.x + screenSize.x * 0.062 + h - 6 + 4, y + 3, clipX, y + h - 3, 0xFF000000, 1, fonts.roboto_light[16], "left", "top", true);
  630.             dxDrawText(v.number, screenPosition.x + screenSize.x * 0.062 + h - 6 + 4, y + 3, clipX, y + h - 3, 0xFF000000, 1, fonts.roboto_light[14], "left", "bottom", true);
  631.  
  632.            
  633.             if (i > 0) then dxDrawRectangle(screenPosition.x + screenSize.x * 0.062, y, screenSize.x * 0.889, 1, 0xFF464646); end -- sep line on the bottom
  634.  
  635.             y = y + h;
  636.         end
  637.  
  638.     end,
  639.  
  640.     click = function(button, state, position)
  641.         if (button ~= "left" or (not state)) then return; end
  642.  
  643.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15)) then -- go back
  644.             goBackToPanelCameFrom();
  645.            
  646.         elseif (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.88, screenPosition.y + screenSize.y * 0.23 / 2 - 12 / 2, 12, 12)) then -- add
  647.             setCurrentPanel(PANEL.CONTACT_ADD_OR_EDIT);
  648.  
  649.         else
  650.             -- tab bar
  651.             if (handleContactTabBarClick()) then return; end
  652.  
  653.  
  654.             -- contact actions
  655.             local y = screenPosition.y + screenSize.y * 0.162;
  656.             local h = panels[PANEL.CONTACTS].contactHeight;
  657.             local actionSize = screenSize * Vector2(0.3, 0.026);
  658.  
  659.             for i = panels[PANEL.CONTACTS].scrollIndex, panels[PANEL.CONTACTS].scrollIndex + panels[PANEL.CONTACTS].drawableContactCount do
  660.                 local contact = phoneData.contacts[i + 1];
  661.                 if (not contact) then break; end
  662.  
  663.                 for j = 0, 4 do
  664.                     if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.936 - (j + 1) * (actionSize.x / 4), y + h / 2 - actionSize.y / 2, actionSize.x, actionSize.y)) then
  665.  
  666.                         if (j == 4) then
  667.                             contact.favorite = not contact.favorite;
  668.                             if (contact.favorite) then addFavoriteContact(contact.id); else removeFavoriteByContactID(contact.id); end
  669.                         elseif (j == 3) then -- call
  670.                             callNumber(contact.number);
  671.  
  672.                         elseif (j == 1) then -- edit
  673.                             panels[PANEL.CONTACT_ADD_OR_EDIT].editedContact = contact;
  674.                             setCurrentPanel(PANEL.CONTACT_ADD_OR_EDIT);
  675.  
  676.                         elseif (j == 2) then -- msg
  677.                             panels[PANEL.CONTACT_MESSENGER].displayedNumberOrName = contact.name;
  678.                             panels[PANEL.CONTACT_MESSENGER].phoneNumber = contact.number;
  679.                             setCurrentPanel(PANEL.CONTACT_MESSENGER);
  680.  
  681.                         elseif (j == 0) then -- delete
  682.                             removeContactByID(contact.id);
  683.                         end
  684.  
  685.                         return;
  686.                     end
  687.                 end
  688.  
  689.  
  690.                 y = y + h;
  691.             end
  692.         end
  693.     end,
  694.  
  695.     scrollIndex = 0
  696. }
  697.  
  698. panels[PANEL.CONTACT_FAVORITES] = {
  699.     init = function()
  700.         local this = panels[PANEL.CONTACT_FAVORITES];
  701.  
  702.         local height = screenSize.y * 0.65;
  703.         this.drawableContactCount = math.floor(height / (screenSize.y * 0.08));
  704.         this.contactHeight = height / this.drawableContactCount;
  705.  
  706.         bindKey("mouse_wheel_up", "down", this.scrollHandler);
  707.         bindKey("mouse_wheel_down", "down", this.scrollHandler);
  708.     end,
  709.  
  710.     deinit = function()
  711.         unbindKey("mouse_wheel_up", "down", this.scrollHandler);
  712.         unbindKey("mouse_wheel_down", "down", this.scrollHandler);
  713.     end,
  714.  
  715.     scrollHandler = function(key)
  716.         if (not isCursorOnRectangle(screenPosition.x, screenPosition.y, screenSize.x, screenSize.y)) then return; end
  717.  
  718.         local this = panels[PANEL.CONTACT_FAVORITES];
  719.  
  720.         if (key == "mouse_wheel_down" and (this.scrollIndex + 1 + this.drawableContactCount < #phoneData.favoriteContacts)) then
  721.             this.scrollIndex = this.scrollIndex + 1;
  722.         elseif (key == "mouse_wheel_up" and (this.scrollIndex - 1 >= 0)) then
  723.             this.scrollIndex = this.scrollIndex - 1;
  724.         end
  725.     end,
  726.  
  727.     render = function()
  728.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  729.  
  730.         -- back button
  731.         dxDrawImage(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15, "files/textures/icons/arrow_left.png");
  732.        
  733.         dxDrawText("Kapcsolatok", screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  734.  
  735.         -- sep. line
  736.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.16, screenSize.x, 1, 0x80464646);
  737.  
  738.         drawContactTabBar();
  739.  
  740.         local y = screenPosition.y + screenSize.y * 0.162;
  741.         local h = panels[PANEL.CONTACT_FAVORITES].contactHeight
  742.         for i = panels[PANEL.CONTACT_FAVORITES].scrollIndex, panels[PANEL.CONTACT_FAVORITES].scrollIndex + panels[PANEL.CONTACT_FAVORITES].drawableContactCount do
  743.             local v = phoneData.favoriteContacts[i + 1];
  744.  
  745.             if (not v) then break; end
  746.  
  747.  
  748.             local clipX = screenPosition.x + screenSize.x * 0.925;
  749.             if (isCursorOnRectangle(screenPosition.x, y, screenSize.x, h)) then
  750.                 local actionSize = screenSize * Vector2(0.3, 0.026);
  751.                 dxDrawImage(screenPosition.x + screenSize.x * 0.936 - actionSize.x - actionSize.x / 4, y + h / 2 - actionSize.y / 2, screenSize.x * 0.042, actionSize.y, "files/textures/icons/contact_app/favorites.png", 0, 0, 0, 0xFFFFD700);
  752.                 dxDrawImage(screenPosition.x + screenSize.x * 0.936 - actionSize.x, y + h / 2 - actionSize.y / 2, actionSize, "files/textures/icons/contact_app/actions.png");
  753.  
  754.                 clipX = screenPosition.x + screenSize.x * 0.936 - actionSize.x - actionSize.x / 4 - 5;
  755.             end
  756.  
  757.             dxDrawImage(screenPosition.x + screenSize.x * 0.062, y + 3, h - 6, h - 6, "files/textures/profile_pics/" .. (v.profilePictureID or 0) .. ".png");
  758.             dxDrawText(v.name, screenPosition.x + screenSize.x * 0.062 + h - 6 + 4, y + 3, clipX, y + h - 3, 0xFF000000, 1, fonts.roboto_light[16], "left", "top", true);
  759.             dxDrawText(v.number, screenPosition.x + screenSize.x * 0.062 + h - 6 + 4, y + 3, clipX, y + h - 3, 0xFF000000, 1, fonts.roboto_light[14], "left", "bottom", true);
  760.  
  761.            
  762.             if (i > 0) then dxDrawRectangle(screenPosition.x + screenSize.x * 0.062, y, screenSize.x * 0.889, 1, 0xFF464646); end -- sep line on the bottom
  763.  
  764.             y = y + h;
  765.         end
  766.  
  767.     end,
  768.  
  769.     click = function(button, state, position)
  770.         if (button ~= "left" or (not state)) then return; end
  771.  
  772.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15)) then -- go back
  773.             goBackToPanelCameFrom();
  774.            
  775.         else
  776.             -- tab bar
  777.             if (handleContactTabBarClick()) then return; end
  778.  
  779.  
  780.             -- contact actions
  781.             local y = screenPosition.y + screenSize.y * 0.162;
  782.             local h = panels[PANEL.CONTACT_FAVORITES].contactHeight
  783.             for i = panels[PANEL.CONTACT_FAVORITES].scrollIndex, panels[PANEL.CONTACT_FAVORITES].scrollIndex + panels[PANEL.CONTACT_FAVORITES].drawableContactCount do
  784.                 local v = phoneData.favoriteContacts[i + 1];
  785.                 if (not v) then break; end
  786.  
  787.                 local actionSize = screenSize * Vector2(0.3, 0.026);
  788.                 for j = 0, 4 do
  789.                     if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.936 - (j + 1) * (actionSize.x / 4), y + h / 2 - actionSize.y / 2, actionSize.x, actionSize.y)) then
  790.  
  791.                         if (j == 4) then
  792.                             removeFavoriteByContactID(v.id);
  793.                             triggerServerEvent("onPlayerChangeContactFavoriteState", localPlayer, v.id, true);
  794.                            
  795.                         elseif (j == 3) then -- call
  796.                             callNumber(v.number);
  797.  
  798.                         elseif (j == 1) then -- edit
  799.                             panels[PANEL.CONTACT_ADD_OR_EDIT].editedContact = v;
  800.                             setCurrentPanel(PANEL.CONTACT_ADD_OR_EDIT);
  801.  
  802.                         elseif (j == 2) then -- msg
  803.                             panels[PANEL.CONTACT_MESSENGER].displayedNumberOrName = v.name;
  804.                             panels[PANEL.CONTACT_MESSENGER].phoneNumber = v.number;
  805.                             setCurrentPanel(PANEL.CONTACT_MESSENGER);
  806.  
  807.                         elseif (j == 0) then -- delete
  808.                             removeContactByID(v.id);
  809.                         end
  810.  
  811.                         return;
  812.                     end
  813.                 end
  814.  
  815.  
  816.                 y = y + h;
  817.             end
  818.         end
  819.     end,
  820.  
  821.     scrollIndex = 0
  822. }
  823.  
  824. panels[PANEL.CALL_HISTORY] = {
  825.     init = function()
  826.         local thisPanel = panels[PANEL.CALL_HISTORY];
  827.  
  828.         local height = screenSize.y * 0.65;
  829.         thisPanel.drawableContactCount = math.floor(height / (screenSize.y * 0.085));
  830.         thisPanel.contactHeight = height / thisPanel.drawableContactCount;
  831.  
  832.         bindKey("mouse_wheel_up", "down", thisPanel.scrollHandler);
  833.         bindKey("mouse_wheel_down", "down", thisPanel.scrollHandler);
  834.  
  835.         refreshCallHistoryContactNames();
  836.         refreshCallHisotryDates();
  837.  
  838.         thisPanel.dateRefreshTimer = setTimer(refreshCallHisotryDates, 60000, 0);
  839.     end,
  840.  
  841.     deinit = function()
  842.         local thisPanel = panels[PANEL.CALL_HISTORY];
  843.  
  844.         unbindKey("mouse_wheel_up", "down", thisPanel.scrollHandler);
  845.         unbindKey("mouse_wheel_down", "down", thisPanel.scrollHandler);
  846.         thisPanel.dateRefreshTimer:destroy();
  847.     end,
  848.  
  849.     scrollHandler = function(key)
  850.         if (not isCursorOnRectangle(screenPosition.x, screenPosition.y, screenSize.x, screenSize.y)) then return; end
  851.  
  852.         local this = panels[PANEL.CALL_HISTORY];
  853.  
  854.         if (key == "mouse_wheel_down" and (this.scrollIndex + 1 + this.drawableContactCount < #phoneData.callHistory)) then
  855.             this.scrollIndex = this.scrollIndex + 1;
  856.         elseif (key == "mouse_wheel_up" and (this.scrollIndex - 1 >= 0)) then
  857.             this.scrollIndex = this.scrollIndex - 1;
  858.         end
  859.     end,
  860.  
  861.     render = function()
  862.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  863.  
  864.         -- back button
  865.         dxDrawImage(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15, "files/textures/icons/arrow_left.png");
  866.  
  867.         dxDrawText("Előzmények", screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  868.  
  869.         -- sep. line
  870.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.16, screenSize.x, 1, 0x80464646);
  871.  
  872.         drawContactTabBar();
  873.  
  874.         local y = screenPosition.y + screenSize.y * 0.162;
  875.         local h = panels[PANEL.CALL_HISTORY].contactHeight
  876.         for i = panels[PANEL.CALL_HISTORY].scrollIndex, panels[PANEL.CALL_HISTORY].scrollIndex + panels[PANEL.CALL_HISTORY].drawableContactCount do
  877.             local v = phoneData.callHistory[i + 1];
  878.  
  879.             if (not v) then break; end
  880.  
  881.  
  882.             local clipX = screenPosition.x + screenSize.x * 0.925;
  883.             if (isCursorOnRectangle(screenPosition.x, y, screenSize.x, h)) then
  884.                 local actionSize = screenSize * Vector2(0.15, 0.026);
  885.                 if (not v.contact) then
  886.                     dxDrawImage(screenPosition.x + screenSize.x * 0.936 - actionSize.x - actionSize.x / 2 - 2, y + h / 2 - actionSize.y / 2, screenSize.x * 0.042, actionSize.y, "files/textures/icons/add.png");
  887.                 end
  888.                 dxDrawImage(screenPosition.x + screenSize.x * 0.936 - actionSize.x, y + h / 2 - actionSize.y / 2, actionSize, "files/textures/icons/contact_app/history_actions.png");
  889.  
  890.                 clipX = screenPosition.x + screenSize.x * 0.936 - actionSize.x - actionSize.x / 2 - 5;
  891.             end
  892.  
  893.             -- number / name
  894.             if (not v.number) then outputChatBox(inspect(v)); end
  895.             dxDrawText(v.contact and v.contact.name or v.number, screenPosition.x + screenSize.x * 0.08, y + 3, clipX, y + h - 3, 0xFF000000, 1, fonts.roboto_regular[16], "left", "top", true);
  896.             -- prof. pics
  897.             --dxDrawImage(screenPosition.x + screenSize.x * 0.062, y + 3, h - 6, h - 6, "files/textures/profile_pics/" .. (v.contact and v.contact.profilePictureID or 0) .. ".png");
  898.             -- call type
  899.             --local iconSize = screenSize.x * 0.05;
  900.             --dxDrawImage(screenPosition.x + screenSize.x * 0.062, y + h - 3 - iconSize, iconSize, iconSize, "files/textures/icons/history_app/call_type/" .. v.type .. ".png", 0, 0, 0, 0xFF000000);
  901.             -- Call date
  902.             dxDrawText(v.text, screenPosition.x + screenSize.x * 0.08, y + h - 3, clipX, y + h - 3, 0xFF646464, 1, fonts.roboto_light[14], "left", "bottom", false, false, false, true);
  903.  
  904.            
  905.             if (i > 0) then dxDrawRectangle(screenPosition.x + screenSize.x * 0.062, y, screenSize.x * 0.889, 1, 0xFF464646); end -- sep line on the bottom
  906.  
  907.             y = y + h;
  908.         end
  909.  
  910.     end,
  911.  
  912.     click = function(button, state, position)
  913.         if (button ~= "left" or (not state)) then return; end
  914.  
  915.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15)) then -- go back
  916.             goBackToPanelCameFrom();
  917.            
  918.         else
  919.             -- tab bar
  920.             if (handleContactTabBarClick()) then return; end
  921.  
  922.  
  923.             -- contact actions
  924.             local y = screenPosition.y + screenSize.y * 0.162;
  925.             local h = panels[PANEL.CALL_HISTORY].contactHeight
  926.             for i = panels[PANEL.CALL_HISTORY].scrollIndex, panels[PANEL.CALL_HISTORY].scrollIndex + panels[PANEL.CALL_HISTORY].drawableContactCount do
  927.                 local v = phoneData.callHistory[i + 1];
  928.                 if (not v) then break; end
  929.  
  930.                 local actionSize = screenSize * Vector2(0.15, 0.026);
  931.                 for j = 0, 2 do
  932.                     if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.936 - (j + 1) * (actionSize.x / 2), y + h / 2 - actionSize.y / 2, actionSize.x, actionSize.y)) then
  933.  
  934.                         if (j == 2) then -- add
  935.                             if (not v.contact) then
  936.                                 setCurrentPanel(PANEL.CONTACT_ADD_OR_EDIT);
  937.                                 panels[PANEL.CONTACT_ADD_OR_EDIT].numberEditBox:setText(v.number);
  938.                             end
  939.                         elseif (j == 1) then -- call
  940.                             callNumber(v.number);
  941.  
  942.                         elseif (j == 0) then --
  943.                             panels[PANEL.CONTACT_MESSENGER].displayedNumberOrName = v.contact and v.contact.name or v.number;
  944.                             panels[PANEL.CONTACT_MESSENGER].phoneNumber = v.number;
  945.                             setCurrentPanel(PANEL.CONTACT_MESSENGER);
  946.                         end
  947.  
  948.                         return;
  949.                     end
  950.                 end
  951.  
  952.  
  953.                 y = y + h;
  954.             end
  955.         end
  956.     end,
  957.  
  958.     scrollIndex = 0
  959. }
  960.  
  961. panels[PANEL.CALL_OUTGOING] = {
  962.     init = function()
  963.  
  964.     end,--callInfo.state
  965.  
  966.     render = function()
  967.         dxDrawImage(screenPosition, screenSize, "files/textures/call_bg.png");
  968.  
  969.         local text = callInfo.state == CALL_STATE.CALLING and CALL_STATE_TEXTS[CALL_STATE.CALLING][callInfo.callerNumber == phoneData.number and 1 or 2] or CALL_STATE_TEXTS[callInfo.state];
  970.         dxDrawText(text, screenPosition.x, screenPosition.y + screenSize.y * 0.08, screenPosition.x + screenSize.x, 0, 0xFFFFFFFF, 1, fonts.roboto_light[14], "center", "top");
  971.         dxDrawText(callInfo.displayedNumberOrName or "Ismeretlen", screenPosition.x, screenPosition.y + screenSize.y * 0.12, screenPosition.x + screenSize.x, 0, 0xFFFFFFFF, 1, fonts.roboto_light[18], "center", "top");
  972.  
  973.  
  974.        local iconSize = screenSize.x * 0.167;
  975.        dxDrawImage(screenPosition + Vector2(screenSize.x / 2 - iconSize / 2, screenSize.y * 0.75), iconSize, iconSize, "files/textures/icons/call_deny.png");
  976.     end,
  977.  
  978.     click = function(button, state, position)
  979.         if (button ~= "left" or (not state)) then return; end
  980.  
  981.         local iconSize = screenSize.x * 0.167;
  982.         if (isCursorOnRectangle(screenPosition.x + screenSize.x / 2 - iconSize / 2, screenPosition.y + screenSize.y * 0.75, iconSize, iconSize)) then -- cancel call
  983.             triggerServerEvent("onPlayerCancelCall", localPlayer);
  984.         end
  985.     end
  986. }
  987.  
  988. panels[PANEL.CALL_INCOMING] = {
  989.     init = function()
  990.        
  991.     end,
  992.  
  993.     render = function()
  994.         dxDrawImage(screenPosition, screenSize, "files/textures/call_bg.png");
  995.  
  996.  
  997.         dxDrawText("Bejövő hívás", screenPosition.x, screenPosition.y + screenSize.y * 0.08, screenPosition.x + screenSize.x, 0, 0xFFFFFFFF, 1, fonts.roboto_light[12], "center", "top");
  998.         dxDrawText(callInfo.displayedNumberOrName or "Ismeretlen", screenPosition.x, screenPosition.y + screenSize.y * 0.12, screenPosition.x + screenSize.x, 0, 0xFFFFFFFF, 1, fonts.roboto_light[14], "center", "top");
  999.  
  1000.  
  1001.         local iconSize = screenSize.x * 0.167;
  1002.         dxDrawImage(screenPosition.x + iconSize, screenPosition.y + screenSize.y * 0.75, iconSize, iconSize, "files/textures/icons/call_deny.png");
  1003.         dxDrawImage(screenPosition.x + screenSize.x - 2 * iconSize, screenPosition.y + screenSize.y * 0.75, iconSize, iconSize, "files/textures/icons/call_accept.png");
  1004.     end,
  1005.  
  1006.     click = function(button, state, position)
  1007.         if (button ~= "left" or (not state)) then return; end
  1008.  
  1009.         local iconSize = screenSize.x * 0.167;
  1010.         if (isCursorOnRectangle(screenPosition.x + iconSize, screenPosition.y + screenSize.y * 0.75, iconSize, iconSize)) then
  1011.             triggerServerEvent("onPlayerCancelCall", localPlayer);
  1012.  
  1013.         elseif (isCursorOnRectangle(screenPosition.x + screenSize.x - 2 * iconSize, screenPosition.y + screenSize.y * 0.75, iconSize, iconSize)) then
  1014.             triggerServerEvent("onPlayerAcceptCall", localPlayer);
  1015.  
  1016.         end
  1017.     end
  1018. }
  1019.  
  1020. panels[PANEL.CALL_CHAT] = {
  1021.     init = function()
  1022.         local thisPanel = panels[PANEL.CALL_CHAT];
  1023.  
  1024.         local guiBrowser = GuiBrowser(screenPosition + screenSize * Vector2(0.018, 0.162), screenSize * Vector2(1 - 2 * 0.018, 1 - 0.162 - 0.03), true, false, false);
  1025.         thisPanel.guiBrowser = guiBrowser;
  1026.         thisPanel.browserDocumentReady = false;
  1027.         thisPanel.messagesToAddCache = {};
  1028.  
  1029.         addEventHandler("onClientBrowserCreated", guiBrowser:getBrowser(),
  1030.             function()
  1031.                 source:loadURL("http://mta/local/files/html/messenger/index.html");
  1032.                 addEventHandler("onClientPlayerSendMessage", source, thisPanel.messageSendHandler);
  1033.  
  1034.                 thisPanel.browserDocumentReady = true;
  1035.  
  1036.                 addEventHandler("onClientBrowserDocumentReady", panels[currentPanelID].guiBrowser:getBrowser(),
  1037.                     function()
  1038.                         for _, v in pairs(thisPanel.messagesToAddCache) do
  1039.                             thisPanel.guiBrowser:getBrowser():executeJavascript(("addMessage(%q, %q, 0)"):format(unpack(v)));
  1040.                         end
  1041.                     end
  1042.                 );
  1043.             end
  1044.         );
  1045.     end,
  1046.    
  1047.     deinit = function()
  1048.         panels[PANEL.CALL_CHAT].guiBrowser:destroy();
  1049.         panels[PANEL.CALL_CHAT].browserDocumentReady = false;
  1050.     end,
  1051.  
  1052.     messageSendHandler = function(message)
  1053.         if (callInfo.state == CALL_STATE.TALKING) then
  1054.             panels[PANEL.CALL_CHAT].addMessage("me", message);
  1055.             triggerServerEvent("onPlayerSendCallChatMessage", localPlayer, message);
  1056.         end
  1057.     end,
  1058.  
  1059.     addMessage = function(type, message)
  1060.         local thisPanel = panels[PANEL.CALL_CHAT];
  1061.  
  1062.         if (thisPanel.browserDocumentReady) then
  1063.             panels[PANEL.CALL_CHAT].guiBrowser:getBrowser():executeJavascript(("addMessage(%q, %q, 0)"):format(type, message));
  1064.         else
  1065.             table.insert(thisPanel.messagesToAddCache, {type, message});
  1066.         end
  1067.     end,
  1068.  
  1069.     addMessages = function(messages)
  1070.         local thisPanel = panels[PANEL.CALL_CHAT];
  1071.  
  1072.         if (thisPanel.browserDocumentReady) then
  1073.             for _, msg in pairs(messages) do
  1074.                 thisPanel.guiBrowser:getBrowser():executeJavascript(("addMessage(%q, %q, 0)"):format(msg.sentBy == phoneData.number and "me" or "other", msg.messages));
  1075.             end
  1076.         else
  1077.             for _, msg in pairs(messages) do
  1078.                 table.insert(thisPanel.messagesToAddCache, {msg.sentBy == phoneData.number and "me" or "other", msg.message});
  1079.             end
  1080.         end
  1081.     end,
  1082.  
  1083.     render = function()
  1084.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  1085.  
  1086.         local iconSize = screenSize.x * 0.1;
  1087.         dxDrawImage(screenPosition.x + screenSize.x * (1 - 0.07) - iconSize, screenPosition.y + screenSize.y * 0.23 / 2 - iconSize / 2, iconSize, iconSize, "files/textures/icons/call_deny.png");
  1088.  
  1089.  
  1090.         dxDrawText(callInfo.displayedNumberOrName, screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  1091.  
  1092.         -- sep. line
  1093.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.16, screenSize.x, 1, 0x80464646);
  1094.  
  1095.     end,
  1096.  
  1097.     click = function(button, state)
  1098.         if (button ~= "left" or (not state)) then return; end
  1099.        
  1100.         local iconSize = screenSize.x * 0.1;
  1101.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * (1 - 0.07) - iconSize, screenPosition.y + screenSize.y * 0.23 / 2 - iconSize / 2, iconSize, iconSize)) then
  1102.             triggerServerEvent("onPlayerCancelCall", localPlayer);
  1103.         end
  1104.     end
  1105. }
  1106.  
  1107. --[[ panels[PANEL.MESSAGE_ADD] = {
  1108.     init = function()
  1109.         local thisPanel = panels[PANEL.MESSAGE_ADD];
  1110.         thisPanel.numberEditBox = GuiEdit(-1000, -1000, 0, 0, "", false);
  1111.         thisPanel.numberEditBox.maxLength = 10;
  1112.     end,
  1113.  
  1114.     deinit = function()
  1115.         local thisPanel = panels[PANEL.MESSAGE_ADD];
  1116.         thisPanel.nameEditBox:destroy();
  1117.         thisPanel.numberEditBox:destroy();
  1118.     end,
  1119.  
  1120.     render = function()
  1121.         local thisPanel = panels[PANEL.MESSAGE_ADD];
  1122.  
  1123.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  1124.  
  1125.         -- back button
  1126.         dxDrawImage(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15, "files/textures/icons/arrow_left.png");
  1127.         dxDrawImage(screenPosition.x + screenSize.x * 0.88, screenPosition.y + screenSize.y * 0.23 / 2 - 12 / 2, 12, 12, "files/textures/icons/add.png");
  1128.  
  1129.         dxDrawText("Üzenet hozzáadása", screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  1130.  
  1131.         -- sep. line
  1132.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.23, screenSize.x, 2, 0x80464646);
  1133.  
  1134.         local fontHeight = dxGetFontHeight(1, fonts.roboto_medium[12]);
  1135.         dxDrawText("Telefonszám: ", screenPosition.x + 15, screenPosition.y + screenSize.y * 0.39, screenPosition.x + screenSize.x - 15, 0, 0xFF464646, 1, fonts.roboto_medium[16], "left", "top")
  1136.         dxDrawText(thisPanel.numberEditBox:getText(), screenPosition.x + 15, screenPosition.y + screenSize.y * 0.39, screenPosition.x + screenSize.x - 15, 0, 0xFF464646, 1, fonts.roboto_light[16], "right", "top")
  1137.         dxDrawRectangle(screenPosition.x + 15, screenPosition.y + screenSize.y * 0.39 + fontHeight + 2, screenSize.x - 30, 1, 0xFF464646, false, false);
  1138.     end,
  1139.  
  1140.     click = function(button, state, position)
  1141.         if (button ~= "left" or (not state)) then return; end
  1142.         local thisPanel = panels[PANEL.MESSAGE_ADD];
  1143.  
  1144.         local fontHeight = dxGetFontHeight(1, fonts.roboto_medium[14]);
  1145.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15)) then
  1146.             goBackToPanelCameFrom();
  1147.  
  1148.         elseif (isCursorOnRectangle(screenPosition.x + 15, screenPosition.y + screenSize.y * 0.39, screenSize.x - 30, fontHeight)) then -- focus number field
  1149.             thisPanel.numberEditBox:bringToFront();
  1150.             thisPanel.numberEditBox:setCaretIndex(#thisPanel.numberEditBox:getText());
  1151.  
  1152.         elseif (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.88, screenPosition.y + screenSize.y * 0.23 / 2 - 12 / 2, 12, 12)) then -- add
  1153.             local number = tonumber(thisPanel.numberEditBox:getText());
  1154.            
  1155.             if (not checkIfNumberIsValidAndAlertIfNot(tostring(number))) then return; end
  1156.            
  1157.             panels[PANEL.CONTACT_MESSENGER].phoneNumber = number;
  1158.             goBackToPanelCameFrom();    
  1159.         end
  1160.     end,
  1161. }
  1162.  ]]
  1163. panels[PANEL.MESSAGES] = {
  1164.     init = function()
  1165.         local thisPanel = panels[PANEL.MESSAGES];
  1166.  
  1167.         local height = screenSize.y * 0.65;
  1168.         thisPanel.drawableContactCount = math.floor(height / (screenSize.y * 0.08));
  1169.         thisPanel.contactHeight = height / thisPanel.drawableContactCount;
  1170.  
  1171.         bindKey("mouse_wheel_up", "down", thisPanel.scrollHandler);
  1172.         bindKey("mouse_wheel_down", "down", thisPanel.scrollHandler);
  1173.     end,
  1174.  
  1175.     deinit = function()
  1176.         unbindKey("mouse_wheel_up", "down", this.scrollHandler);
  1177.         unbindKey("mouse_wheel_down", "down", this.scrollHandler);
  1178.     end,
  1179.  
  1180.     scrollHandler = function(key)
  1181.         if (not isCursorOnRectangle(screenPosition.x, screenPosition.y, screenSize.x, screenSize.y)) then return; end
  1182.  
  1183.         local this = panels[PANEL.MESSAGES];
  1184.  
  1185.         if (key == "mouse_wheel_down" and (this.scrollIndex + 1 + this.drawableContactCount < #phoneData.contacts)) then
  1186.             this.scrollIndex = this.scrollIndex + 1;
  1187.         elseif (key == "mouse_wheel_up" and (this.scrollIndex - 1 >= 0)) then
  1188.             this.scrollIndex = this.scrollIndex - 1;
  1189.         end
  1190.     end,
  1191.  
  1192.     render = function()
  1193.         local thisPanel = panels[PANEL.MESSAGES];
  1194.  
  1195.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  1196.  
  1197.         -- back button
  1198.         dxDrawImage(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15, "files/textures/icons/arrow_left.png");
  1199.         dxDrawImage(screenPosition.x + screenSize.x * 0.88, screenPosition.y + screenSize.y * 0.23 / 2 - 12 / 2, 12, 12, "files/textures/icons/add.png");
  1200.        
  1201.         dxDrawText("Üzenetek", screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  1202.  
  1203.         -- sep. line
  1204.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.16, screenSize.x, 1, 0x80464646);
  1205.  
  1206.         local y = screenPosition.y + screenSize.y * 0.162;
  1207.         local h = thisPanel.contactHeight
  1208.         for i = thisPanel.scrollIndex, thisPanel.scrollIndex + thisPanel.drawableContactCount do
  1209.             local v = phoneData.messages[i + 1];
  1210.             if (not v) then
  1211.                 --thisPanel.scrollIndex = #phoneData.messages - thisPanel.drawableContactCount;
  1212.                 break;
  1213.             end
  1214.             --outputChatBox(i)
  1215.  
  1216.             local clipX = screenPosition.x + screenSize.x * 0.925;
  1217.             if (not v.contact and isCursorOnRectangle(screenPosition.x, y, screenSize.x, h)) then
  1218.                 local iconSize = screenSize.y * 0.026;
  1219.                 clipX = screenPosition.x + screenSize.x * 0.9 - iconSize - 8;
  1220.  
  1221.                 --dxDrawImage(clipX + 8, y + h / 2 - iconSize / 2, iconSize, iconSize, "files/textures/icons/message_actions.png");
  1222.             end
  1223.  
  1224.             dxDrawImage(screenPosition.x + screenSize.x * 0.062, y + 3, h - 6, h - 6, "files/textures/profile_pics/0.png");
  1225.  
  1226.             local lastMessage = v[#v];
  1227.    
  1228.             local contact = getContactFromNumber(v.number);
  1229.             dxDrawText((contact and contact.name or v.number) .. ((lastMessage and not lastMessage.read) and "[új üzenet]" or ""), screenPosition.x + screenSize.x * 0.062 + h - 6 + 4, y + 3, clipX, y + h - 3, 0xFF000000, 1, fonts.roboto_light[16], "left", "top", true);
  1230.  
  1231.             -- draw last message
  1232.             local text = lastMessage and lastMessage.isSender and ("Én: " .. lastMessage.text) or ((contact and (contact.name .. ":") or "") .. lastMessage.text);
  1233.             local color = lastMessage and lastMessage.read and 0xFF464646 or 0xFF000000;
  1234.             dxDrawText(text, screenPosition.x + screenSize.x * 0.062 + h - 6 + 4, y + 3, clipX, y + h - 3, color, 1, fonts.roboto_light[14], "left", "bottom", true);
  1235.  
  1236.            
  1237.             if (i > 0) then dxDrawRectangle(screenPosition.x + screenSize.x * 0.062, y, screenSize.x * 0.889, 1, 0xFF464646); end -- sep line on the bottom
  1238.  
  1239.             y = y + h;
  1240.         end
  1241.  
  1242.     end,
  1243.  
  1244.     click = function(button, state, position)
  1245.         if (button ~= "left" or (not state)) then return; end
  1246.         local thisPanel = panels[PANEL.MESSAGES];
  1247.  
  1248.  
  1249.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15)) then -- go back
  1250.             goBackToPanelCameFrom();
  1251.            
  1252.         elseif (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.88, screenPosition.y + screenSize.y * 0.23 / 2 - 12 / 2, 12, 12)) then -- add
  1253.             panels[PANEL.CONTACT_MESSENGER].phoneNumber = nil; -- so the user can enter one.
  1254.             setCurrentPanel(PANEL.CONTACT_MESSENGER);
  1255.  
  1256.         else
  1257.             -- contact actions
  1258.             local y = screenPosition.y + screenSize.y * 0.162;
  1259.             local h = thisPanel.contactHeight;
  1260.             local actionSize = screenSize * Vector2(0.3, 0.026);
  1261.  
  1262.             for i = thisPanel.scrollIndex, thisPanel.scrollIndex + thisPanel.drawableContactCount do
  1263.                 local v = phoneData.messages[i + 1];
  1264.                 if (not v) then break; end
  1265.  
  1266.                 if (isCursorOnRectangle(screenPosition.x, y, screenSize.x, h)) then
  1267.                     -- TODO icons click test thing here
  1268.  
  1269.                     -- open chat with the clicked preson
  1270.                    
  1271.                     local contact = getContactFromNumber(v.number);
  1272.                     panels[PANEL.CONTACT_MESSENGER].displayedNumberOrName = contact and contact.name or v.number;
  1273.                     panels[PANEL.CONTACT_MESSENGER].phoneNumber = v.number;
  1274.  
  1275.                     setCurrentPanel(PANEL.CONTACT_MESSENGER);
  1276.                     break;
  1277.                 end
  1278.  
  1279.  
  1280.                 y = y + h;
  1281.             end
  1282.         end
  1283.     end,
  1284.  
  1285.     scrollIndex = 0
  1286. }
  1287. addEventHandler("onClientResourceStop", resourceRoot,
  1288.     function()
  1289.         if (currentPanelID == PANEL.CAMERA) then
  1290.             panels[currentPanelID].deinit();
  1291.         end
  1292.     end
  1293. );
  1294. local salt = "~>>ˇ~^˘°˛`_BlueMTA";
  1295. panels[PANEL.CAMERA] = {
  1296.     init = function()
  1297.         local thisPanel = panels[PANEL.CAMERA];
  1298.    
  1299.  
  1300.         thisPanel.wasHudVisible = localPlayer:getData(salt .. "hudVisible" .. salt);
  1301.         localPlayer:setData(salt .. "hudVisible" .. salt, false);
  1302.  
  1303.         thisPanel.scrSource = DxScreenSource(scrSize);
  1304.         thisPanel.lookAtOffset = Vector3();
  1305.  
  1306.         exports['cr_animation']:applyAnimation(localPlayer, "SHOP", "ROB_Loop_Threat", -1, false, true, false);
  1307.         localPlayer:setData(salt .. "forceAnimation" .. salt,  {"NEIRDFELUL", "NEIRDFELUL"});
  1308.         --localPlayer:setAnimation("SHOP", "ROB_Loop_Threat", -1, false, true, false);
  1309.     end,
  1310.  
  1311.     deinit = function()
  1312.         local thisPanel = panels[PANEL.CAMERA];
  1313.  
  1314.         setCameraTarget(localPlayer, localPlayer);
  1315.         localPlayer:setData(salt .. "forceAnimation" .. salt, {"", ""})
  1316.         --exports['cr_animation']:removeAnimation(localPlayer)
  1317.         localPlayer:setData(salt .. "hudVisible" .. salt, thisPanel.wasHudVisible);
  1318.     end,
  1319.  
  1320.     render = function()
  1321.         local thisPanel = panels[PANEL.CAMERA];
  1322.        
  1323.         thisPanel.scrSource:update();
  1324.  
  1325.         dxDrawImage(scrSize / 2 -  Vector2(screenSize.y, screenSize.x) / 2, screenSize.y, screenSize.x, thisPanel.scrSource);
  1326.         dxDrawImage(scrSize / 2 -  Vector2(screenSize.y, screenSize.x) / 2 + Vector2(screenSize.y * 0.038), screenSize.y * 0.978, screenSize.x, "files/textures/camerabg.png");
  1327.  
  1328.         setPedLookAt(localPlayer, localPlayer:getBonePosition(25));
  1329.         setCameraMatrix(localPlayer:getBonePosition(25) + Vector3(0, 0, 0.2), localPlayer:getBonePosition(6) + thisPanel.lookAtOffset);
  1330.  
  1331.         dxDrawText("Visszalépni a 'backspace' gomb segítségével tudsz.", 0, scrSize.y - 200, scrSize.x, scrSize.y, 0xFFFFFFFF, 1, fonts.roboto_light[26], "center", "top", false, false, false, true);
  1332.     end,
  1333.    
  1334.     click = function(button, state, position)
  1335.         if (button ~= "left" or (not state)) then return; end
  1336.         local thisPanel = panels[PANEL.CAMERA];
  1337.  
  1338.         -- 927, 720
  1339.         -- 795, 218
  1340.         -- 132, 502
  1341.         -- 0,47, 0.84
  1342.        
  1343.         local pos = scrSize / 2 - Vector2(size.y, size.x) / 2 + Vector2(screenSize.y * 0.84, screenSize.x * 0.47);
  1344.         if (isCursorOnRectangle(pos.x, pos.y, 64, 64)) then
  1345.             local pixelSZ = thisPanel.scrSource:getPixels();
  1346.             if (not pixelSZ) then exports.cr_infobox:addBox("error", "Nem sikerült lementeni a képet. Lehetséges, hogy nincs engedélyezve a képernyő feltöltés az MTAn belül."); return; end
  1347.  
  1348.             local d = getRealTime();
  1349.  
  1350.             local fname = ("%i.%.2i.%.2i - %.2i-%.2i-%.2i.png"):format(d.year + 1900, d.month + 1, d.monthday, d.hour, d.minute, d.second);
  1351.             local f = File.create("photos/" .. fname);
  1352.             if (not f) then exports.cr_infobox:addBox("error", "Nem sikerült lementeni a képet - A fájl létehozása sikertelen "); return; end
  1353.             f:write(dxConvertPixels(pixelSZ, "png"));
  1354.             f:close();
  1355.  
  1356.             exports.cr_infobox:addBox("info", "A kép le lett mentve. Az '<MTA elérési útvonal>/mods/deathmatch/cr_phone/photos/' mappában találod '" .. fname .. "' név alatt.");
  1357.         end
  1358.  
  1359.     end
  1360. }
  1361.  
  1362. addEvent("onClientPlayerSendMessage");
  1363. addEvent("onMessageScrollBarOnTop");
  1364. panels[PANEL.CONTACT_MESSENGER] = {
  1365.     init = function()
  1366.         local thisPanel = panels[PANEL.CONTACT_MESSENGER];
  1367.  
  1368.         if (thisPanel.phoneNumber) then  
  1369.             triggerServerEvent("onPlayerRequestPhoneMessages", localPlayer, thisPanel.phoneNumber);
  1370.         else
  1371.             thisPanel.numberEditBox = GuiEdit(-1000, -1000, 0, 0, "", false);
  1372.             thisPanel.numberEditBox:setMaxLength(10);
  1373.         end
  1374.  
  1375.         local guiBrowser = GuiBrowser(screenPosition + screenSize * Vector2(0.018, 0.162), screenSize * Vector2(1 - 2 * 0.018, 1 - 0.162 - 0.03), true, false, false);
  1376.         thisPanel.guiBrowser = guiBrowser;
  1377.    
  1378.         thisPanel.browserDocumentReady = false;
  1379.         thisPanel.messageToAddCache = {};
  1380.         addEventHandler("onClientBrowserCreated", guiBrowser:getBrowser(),
  1381.             function()
  1382.                 source:loadURL("http://mta/local/files/html/messenger/index.html");
  1383.                
  1384.                 addEventHandler("onClientPlayerSendMessage", source,
  1385.                     function(message)
  1386.                         if (not thisPanel.phoneNumber) then
  1387.                             if not (checkIfNumberIsValidAndAlertIfNot(thisPanel.numberEditBox:getText())) then return; end
  1388.                             thisPanel.phoneNumber = tonumber(thisPanel.numberEditBox:getText());
  1389.                             thisPanel.numberEditBox:destroy();
  1390.  
  1391.                             triggerServerEvent("onPlayerRequestPhoneMessages", localPlayer);
  1392.                         end
  1393.                         triggerServerEvent("onClientPlayerSendSMS", localPlayer, thisPanel.phoneNumber, message);
  1394.                     end
  1395.                 );
  1396.  
  1397.                 addEventHandler("onClientBrowserDocumentReady", source,
  1398.                     function()
  1399.                         thisPanel.browserDocumentReady = true;
  1400.                         outputConsole("messageToAddCache\n"..inspect(thisPanel.messageToAddCache));
  1401.                        
  1402.                         for _, v in pairs(thisPanel.messageToAddCache) do
  1403.                             thisPanel.guiBrowser:getBrowser():executeJavascript(("addMessage(%q, %q, %i)"):format(unpack(v)));                        
  1404.                         end
  1405.                     end
  1406.                 );
  1407.             end
  1408.         );
  1409.     end,
  1410.    
  1411.     deinit = function()
  1412.         local thisPanel = panels[PANEL.CONTACT_MESSENGER];
  1413.  
  1414.         thisPanel.guiBrowser:destroy();
  1415.         if (isElement(thisPanel.numberEditBox)) then thisPanel.numberEditBox:destroy(); end
  1416.     end,
  1417.  
  1418.     addMessage = function(type, message, state)
  1419.         local thisPanel = panels[PANEL.CONTACT_MESSENGER];
  1420.  
  1421.         if (thisPanel.browserDocumentReady) then
  1422.             thisPanel.guiBrowser:getBrowser():executeJavascript(("addMessage(%q, %q, %i)"):format(type, message, state or 0));
  1423.         else
  1424.             table.insert(thisPanel.messageToAddCache, {type, message, state or 0});
  1425.         end
  1426.     end,
  1427.  
  1428.     clear = function()
  1429.         local thisPanel = panels[PANEL.CONTACT_MESSENGER];
  1430.  
  1431.         if (thisPanel.browserDocumentReady) then
  1432.             panels[PANEL.CONTACT_MESSENGER].guiBrowser:getBrowser():executeJavascript("document.getElementById(\"messages\").innerHTML = ''");
  1433.         end
  1434.     end,
  1435.  
  1436.     --[[ addMessagesToTop = function(messages)
  1437.         local thisPanel = panels[PANEL.CONTACT_MESSENGER];
  1438.         thisPanel.requestedMessges = false;
  1439.  
  1440.         if (thisPanel.browserDocumentReady) then
  1441.             for k, v in pairs(messages) do
  1442.                 thisPanel.guiBrowser:getBrowser():executeJavascript(("addMessageToTop(%q, %q, %i, 1)"):format(v.isSender and "me" or "other", v.text, v.state));
  1443.             end
  1444.         else
  1445.             addEventHandler("onClientBrowserDocumentReady", panels[currentPanelID].guiBrowser:getBrowser(),
  1446.                 function()
  1447.                     for k, v in pairs(messages) do
  1448.                         thisPanel.guiBrowser:getBrowser():executeJavascript(("addMessageToTop(%q, %q, %i, 1)"):format(v.isSender and "me" or "other", v.text, v.state));
  1449.                     end
  1450.                 end
  1451.             );
  1452.         end
  1453.     end, ]]
  1454.  
  1455.     render = function()
  1456.         local thisPanel = panels[PANEL.CONTACT_MESSENGER];
  1457.  
  1458.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  1459.  
  1460.         -- back button
  1461.         dxDrawImage(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15, "files/textures/icons/arrow_left.png");
  1462.        
  1463.         local text = not thisPanel.phoneNumber and thisPanel.numberEditBox:getText();
  1464.         local number = thisPanel.phoneNumber or tonumber(text);
  1465.         local contact = number and getContactFromNumber(number);
  1466.         dxDrawText(contact and contact.name or number or (text and (#text > 0 and text or "Írj be egy számot")) , screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  1467.  
  1468.         -- sep. line
  1469.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.16, screenSize.x, 1, 0x80464646);
  1470.     end,
  1471.  
  1472.     click = function(button, state)
  1473.         if (button ~= "left" or (not state)) then return; end
  1474.         local thisPanel = panels[PANEL.CONTACT_MESSENGER];
  1475.  
  1476.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15)) then -- go back
  1477.             goBackToPanelCameFrom();
  1478.         elseif (not thisPanel.phoneNumber and isCursorOnRectangle(screenPosition.x, screenPosition.y, screenSize.x, screenSize.y * 0.16)) then -- focus edit field
  1479.             thisPanel.numberEditBox:bringToFront();
  1480.             thisPanel.numberEditBox:setCaretIndex(#thisPanel.numberEditBox:getText());
  1481.  
  1482.         end
  1483.     end,
  1484.  
  1485.     phoneNumber = 0 -- parnter number
  1486. }
  1487.  
  1488. panels[PANEL.CALL_KEYPAD] = {
  1489.     init = function()
  1490.         addEventHandler("onClientCharacter", root, panels[PANEL.CALL_KEYPAD].onClientCharacter);
  1491.         addEventHandler("onClientKey", root, panels[PANEL.CALL_KEYPAD].onClientKey);
  1492.     end,
  1493.  
  1494.     deinit = function()
  1495.         removeEventHandler("onClientCharacter", root, panels[PANEL.CALL_KEYPAD].onClientCharacter);
  1496.         removeEventHandler("onClientKey", root, panels[PANEL.CALL_KEYPAD].onClientKey);
  1497.     end,
  1498.  
  1499.     onClientCharacter = function(key)
  1500.         local thisPanel = panels[PANEL.CALL_KEYPAD];
  1501.         if (#thisPanel.enteredNumber > 12) then return; end
  1502.  
  1503.         -- letter -> number conversation
  1504.         local char = string.byte(string.upper(key)) - string.byte("A"); -- A's ASCII is 65, thus if A is pressed then its 0, if Z its 25, so we have 26 letters.
  1505.         if (char >= 0 and char <= 25) then
  1506.             local number = 0;
  1507.             if (char == 25) then  -- 'Z' is on 9, not 10, as the code would calculate it.
  1508.                 number = 9;
  1509.             elseif (char == 18) then -- 'S' is on 7, not 8
  1510.                 number = 7;
  1511.             elseif (char == 21) then -- 'V' is on 8, not 9
  1512.                 number = 8;
  1513.             elseif (char >= 22) then
  1514.                 number = 9;
  1515.             else
  1516.                 number = tostring(2 + math.floor(char / 3));
  1517.             end
  1518.             thisPanel.enteredNumber = thisPanel.enteredNumber .. number;
  1519.  
  1520.         elseif (tonumber(key) or key == "#" or key == "*" or key == "+") then
  1521.             thisPanel.enteredNumber = thisPanel.enteredNumber .. key;
  1522.         end
  1523.  
  1524.     end,
  1525.  
  1526.     onClientKey = function(key, state)
  1527.         if (not state) then return; end
  1528.         local thisPanel = panels[PANEL.CALL_KEYPAD];    
  1529.  
  1530.                    
  1531.         if (key == "backspace") then
  1532.             if (#thisPanel.enteredNumber == 0) then return; end
  1533.             thisPanel.enteredNumber = string.sub(thisPanel.enteredNumber, 0, #thisPanel.enteredNumber - 1);
  1534.         elseif (key == "enter") then
  1535.             local number = tonumber(thisPanel.enteredNumber);
  1536.             if (number) then
  1537.                 callNumber(number);                            
  1538.             else
  1539.                 --todo: infobox invalid number
  1540.             end
  1541.         end
  1542.     end,
  1543.  
  1544.     render = function()
  1545.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  1546.  
  1547.         -- back button
  1548.         dxDrawImage(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15, "files/textures/icons/arrow_left.png");
  1549.        
  1550.         dxDrawText("Gombok", screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  1551.  
  1552.         -- sep. line
  1553.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.16, screenSize.x, 1, 0x80464646);
  1554.  
  1555.         dxDrawText(panels[PANEL.CALL_KEYPAD].enteredNumber, screenPosition + screenSize * Vector2(0, 0.160), screenPosition + screenSize * Vector2(1, 0.3), 0xFF000000, 1, fonts.roboto_medium[24], "center", "center", true, true);
  1556.  
  1557.         local keypadSize = screenSize * Vector2(1, 0.6);
  1558.         local keypadPosition = screenPosition + screenSize * Vector2(0, 0.3);
  1559.  
  1560.         dxDrawImage(keypadPosition, keypadSize, "files/textures/icons/contact_app/keypad_bg.png");
  1561.     end,
  1562.  
  1563.     click = function(button, state)
  1564.         if (button ~= "left" or (not state)) then return; end
  1565.      
  1566.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15)) then -- go back
  1567.             goBackToPanelCameFrom();
  1568.             return;
  1569.         end
  1570.  
  1571.         local keypadPosition = screenPosition + screenSize * Vector2(0.12, 0.3); -- 0.100, 0.199
  1572.         local keySize = screenSize * Vector2(0.206, 0.115);
  1573.         for x = 0, 2 do
  1574.             for y = 0, 4 do
  1575.                 local keyPos = keypadPosition + screenSize * Vector2(x * 0.280, y * 0.125);
  1576.                 if (isCursorOnRectangle(keyPos.x, keyPos.y, keySize.x, keySize.y)) then
  1577.                     local thisPanel = panels[PANEL.CALL_KEYPAD];
  1578.  
  1579.                     if (#thisPanel.enteredNumber > 12) then return; end
  1580.  
  1581.                     if (y <= 2) then -- numbers
  1582.                         thisPanel.enteredNumber = thisPanel.enteredNumber .. tostring(1 + y * 3 + x);
  1583.  
  1584.                     elseif (y == 3) then -- *, 0, #
  1585.                         if (x == 0) then -- *
  1586.                             thisPanel.enteredNumber  = thisPanel.enteredNumber .. "*";
  1587.                         elseif (x == 1) then -- 0
  1588.                             thisPanel.enteredNumber  = thisPanel.enteredNumber .. "0";
  1589.                         else
  1590.                             thisPanel.enteredNumber  = thisPanel.enteredNumber .. "#";
  1591.                         end
  1592.  
  1593.                     elseif (x == 1) then -- call(only here if y == 4, so no need to check that as well.)
  1594.                         local number = tonumber(thisPanel.enteredNumber);
  1595.                         if (not checkIfNumberIsValidAndAlertIfNot(tostring(number))) then return; end
  1596.  
  1597.                         if (number) then
  1598.                             callNumber(number);                            
  1599.                         else
  1600.                             exports['cr_infobox']:addBox("error", "Helytelen telefonszámot írtál be");
  1601.                         end
  1602.                     end
  1603.                     break;
  1604.                 end
  1605.             end
  1606.         end
  1607.     end,
  1608.  
  1609.     enteredNumber = ""
  1610. }
  1611.  
  1612. panels[PANEL.SETTINGS] = {
  1613.     render = function()
  1614.         dxDrawRectangle(screenPosition, screenSize, 0xFFFFFFFF);
  1615.  
  1616.         -- back button
  1617.         dxDrawImage(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15, "files/textures/icons/arrow_left.png");
  1618.  
  1619.         dxDrawText("Beállítások", screenPosition, screenPosition + Vector2(screenSize.x, screenSize.y * 0.23), 0xFF000000, 1, fonts.roboto_medium[18], "center", "center", true, true)
  1620.  
  1621.         -- sep. line
  1622.         dxDrawRectangle(screenPosition.x, screenPosition.y + screenSize.y * 0.16, screenSize.x, 1, 0x80464646);
  1623.  
  1624.         local h = screenSize.y * 0.084;  
  1625.         local iconSize = h * 0.8;
  1626.         local marginSide = screenSize.x * 0.028;
  1627.        
  1628.         local y = screenPosition.y + screenSize.y * 0.16 + 0 * h;
  1629.  
  1630.         -- wallpaper change
  1631.         dxDrawImage(screenPosition.x + marginSide, y + h * 0.1, iconSize, iconSize, "files/textures/icons/wallpaper.png");
  1632.         dxDrawText("Háttérkép", screenPosition.x + marginSide + iconSize + 3, y, screenPosition.x + screenSize.x * 0.88, y + h, 0xFF000000, 1, fonts.roboto_medium[12], "left", "center");
  1633.         dxDrawText(phoneData.settings.wallpaper, screenPosition.x + marginSide + iconSize + 3, y, screenPosition.x + screenSize.x * 0.88, y + h, 0xFF464646, 1, fonts.roboto_light [12], "right", "center");
  1634.         dxDrawImage(screenPosition.x + screenSize.x * 0.88 + 10, y + h / 2 - 13 / 2, 8, 13, "files/textures/icons/settings/arrow_right.png");
  1635.         dxDrawRectangle(screenPosition.x + 2 * marginSide, y + h, screenSize.x - 4 * marginSide, 1, 0x80464646); -- sep
  1636.  
  1637.         y = y + h;
  1638.  
  1639.         -- ringtone
  1640.         dxDrawImage(screenPosition.x + marginSide, y + h * 0.1, iconSize, iconSize, "files/textures/icons/menu/call.png");
  1641.         dxDrawText("Csengőhang", screenPosition.x + marginSide + iconSize + 3, y, screenPosition.x + screenSize.x * 0.88, y + h, 0xFF000000, 1, fonts.roboto_medium[12], "left", "center");
  1642.         dxDrawText(phoneData.settings.ringtone, screenPosition.x + screenSize.x * 0.88 - 8 - 10, y + h / 2 - 13 / 2, screenPosition.x + screenSize.x * 0.88 + 10 + 8, y + h / 2 + 13 / 2, 0xFF464646, 1, fonts.roboto_light [12], "center", "center");
  1643.         dxDrawImage(screenPosition.x + screenSize.x * 0.88 - 8 - 10, y + h / 2 - 13 / 2, 8, 13, "files/textures/icons/settings/arrow_left.png");
  1644.         dxDrawImage(screenPosition.x + screenSize.x * 0.88 + 10, y + h / 2 - 13 / 2, 8, 13, "files/textures/icons/settings/arrow_right.png");
  1645.         dxDrawRectangle(screenPosition.x + 2 * marginSide, y + h, screenSize.x - 4 * marginSide, 1, 0x80464646); -- sep
  1646.  
  1647.         y = y + h;
  1648.         -- ringtone volume
  1649.         dxDrawImage(screenPosition.x + marginSide, y + h * 0.1, iconSize, iconSize, "files/textures/icons/menu/call.png");
  1650.         dxDrawText("Csengőhang hangerje", screenPosition.x + marginSide + iconSize + 3, y, screenPosition.x + screenSize.x * 0.88, y + h, 0xFF000000, 1, fonts.roboto_medium[12], "left", "center");
  1651.         local textW = dxGetTextWidth("Csengőhang hangerje", 1, fonts.roboto_medium[12]);
  1652.         local sliderW = screenSize.x - (marginSide + iconSize + 3 + textW + 8) - 2 * marginSide - 10;
  1653.         dxDrawRectangle(screenPosition.x + marginSide + iconSize + 3 + textW + 8 + 5, y + h / 2, sliderW, 2, 0xFF464646);
  1654.         local circleX = phoneData.settings.ringtoneVolume / 100 * sliderW;
  1655.         dxDrawCircle(screenPosition.x + marginSide + iconSize + 3 + textW + 8 + 5 + circleX, y + h / 2, 6, 0, 360, 0xFF464646, 0xFF464646, 256);
  1656.  
  1657.         if (isCursorOnRectangle(screenPosition.x + marginSide + iconSize + 3 + textW + 8 + 5, y, sliderW, h) and getKeyState("mouse1")) then
  1658.             phoneData.settings.ringtoneVolume = (1 - ((screenPosition.x + marginSide + iconSize + 3 + textW + 8 + 5 + sliderW) - cursorPosition.x) / sliderW) * 100;
  1659.         end
  1660.  
  1661.         dxDrawRectangle(screenPosition.x + 2 * marginSide, y + h, screenSize.x - 4 * marginSide, 1, 0x80464646); -- sep
  1662.  
  1663.         -- sms
  1664.  
  1665.         y = y + h;
  1666.         -- ringtone
  1667.         dxDrawImage(screenPosition.x + marginSide, y + h * 0.1, iconSize, iconSize, "files/textures/icons/menu/call.png");
  1668.         dxDrawText("SMS hang", screenPosition.x + marginSide + iconSize + 3, y, screenPosition.x + screenSize.x * 0.88, y + h, 0xFF000000, 1, fonts.roboto_medium[12], "left", "center");
  1669.         dxDrawText(phoneData.settings.smsSound, screenPosition.x + screenSize.x * 0.88 - 8 - 10, y + h / 2 - 13 / 2, screenPosition.x + screenSize.x * 0.88 + 10 + 8, y + h / 2 + 13 / 2, 0xFF464646, 1, fonts.roboto_light [12], "center", "center");
  1670.         dxDrawImage(screenPosition.x + screenSize.x * 0.88 - 8 - 10, y + h / 2 - 13 / 2, 8, 13, "files/textures/icons/settings/arrow_left.png");
  1671.         dxDrawImage(screenPosition.x + screenSize.x * 0.88 + 10, y + h / 2 - 13 / 2, 8, 13, "files/textures/icons/settings/arrow_right.png");
  1672.         dxDrawRectangle(screenPosition.x + 2 * marginSide, y + h, screenSize.x - 4 * marginSide, 1, 0x80464646); -- sep
  1673.  
  1674.         y = y + h;
  1675.  
  1676.         -- ringtone volume
  1677.         dxDrawImage(screenPosition.x + marginSide, y + h * 0.1, iconSize, iconSize, "files/textures/icons/menu/call.png");
  1678.         dxDrawText("SMS hangerő", screenPosition.x + marginSide + iconSize + 3, y, screenPosition.x + screenSize.x * 0.88, y + h, 0xFF000000, 1, fonts.roboto_medium[12], "left", "center");
  1679.         local textW = dxGetTextWidth("SMS hangerő", 1, fonts.roboto_medium[12]);
  1680.         local sliderW = screenSize.x - (marginSide + iconSize + 3 + textW + 8) - 2 * marginSide - 10;
  1681.         dxDrawRectangle(screenPosition.x + marginSide + iconSize + 3 + textW + 8 + 5, y + h / 2, sliderW, 2, 0xFF464646);
  1682.         local circleX = phoneData.settings.smsSoundVolume / 100 * sliderW;
  1683.         dxDrawCircle(screenPosition.x + marginSide + iconSize + 3 + textW + 8 + 5 + circleX, y + h / 2, 6, 0, 360, 0xFF464646, 0xFF464646, 256);
  1684.  
  1685.         if (isCursorOnRectangle(screenPosition.x + marginSide + iconSize + 3 + textW + 8 + 5, y, sliderW, h) and getKeyState("mouse1")) then
  1686.             phoneData.settings.smsSoundVolume = (1 - ((screenPosition.x + marginSide + iconSize + 3 + textW + 8 + 5 + sliderW) - cursorPosition.x) / sliderW) * 100;
  1687.             phoneData.ringtoneVolumeUpdated = true;
  1688.         end
  1689.  
  1690.         dxDrawRectangle(screenPosition.x + 2 * marginSide, y + h, screenSize.x - 4 * marginSide, 1, 0x80464646); -- sep
  1691.     end,
  1692.  
  1693.     click = function(button, state, position)
  1694.         if (button ~= "left" or (not state)) then return; end
  1695.  
  1696.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.07, screenPosition.y + screenSize.y * 0.23 / 2 - 15 / 2, 9, 15)) then -- go back
  1697.             goBackToPanelCameFrom();
  1698.  
  1699.         else
  1700.             local h = screenSize.y * 0.084;  
  1701.             local iconSize = h * 0.8;
  1702.             local marginSide = screenSize.x * 0.028;
  1703.            
  1704.             local y = screenPosition.y + screenSize.y * 0.16 + 0 * h;
  1705.  
  1706.             if (isCursorOnRectangle(screenPosition.x, y, screenSize.x, h)) then -- wallpaper change
  1707.                 setCurrentPanel(PANEL.WALLPAPER_CHANGE);    
  1708.             end
  1709.  
  1710.             y = y + h;
  1711.             if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.88 - 8 - 10, y + h / 2 - 13 / 2, 8, 13)) then -- ringtone -
  1712.                 if (setRingtone(phoneData.settings.ringtone - 1)) then playRingtoneSound(); end
  1713.             elseif (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.88 + 10, y + h / 2 - 13 / 2, 8, 13)) then -- ringtone +
  1714.                 if (setRingtone(phoneData.settings.ringtone + 1)) then playRingtoneSound(); end
  1715.             end
  1716.            
  1717.             y = y + 2 * h;
  1718.             if (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.88 - 8 - 10, y + h / 2 - 13 / 2, 8, 13)) then -- sms sound -
  1719.                 if (setSMSSound(phoneData.settings.smsSound - 1)) then playSMSSound(); end
  1720.             elseif (isCursorOnRectangle(screenPosition.x + screenSize.x * 0.88 + 10, y + h / 2 - 13 / 2, 8, 13)) then -- sms sound +
  1721.                 if (setSMSSound(phoneData.settings.smsSound + 1)) then playSMSSound(); end
  1722.             end
  1723.         end
  1724.     end,
  1725.  
  1726.     scrollIndex = 0
  1727. }
  1728.  
  1729. panels[PANEL.WALLPAPER_CHANGE] = {
  1730.     render = function()
  1731.         dxDrawImage(screenPosition, screenSize, "files/textures/wallpapers/" .. phoneData.settings.wallpaper .. ".png");
  1732.  
  1733.         dxDrawImage(screenPosition.x + 5, screenPosition.y + screenSize.y / 2 - 13 / 2, 8, 13, "files/textures/icons/settings/arrow_left.png");
  1734.         dxDrawImage(screenPosition.x + screenSize.x - 5 - 8, screenPosition.y + screenSize.y / 2 - 13 / 2, 8, 13, "files/textures/icons/settings/arrow_right.png");
  1735.  
  1736.         local x, y = screenPosition.x + screenSize.x * (0.5 - 0.25 / 2), screenPosition.y + screenSize.y * 0.87;
  1737.         dxDrawRectangle(x, y, screenSize.x * 0.25, screenSize.y * 0.08, 0xFF3d7abc);
  1738.         dxDrawText("Mentés", x, y, x + screenSize.x * 0.25, y + screenSize.y * 0.08, 0xFF000000, 1, fonts.roboto_light[12], "center", "center", true, true);
  1739.     end,
  1740.  
  1741.     click = function(button, state)
  1742.         if (button ~= "left" or (not state)) then return; end
  1743.  
  1744.         if (isCursorOnRectangle(screenPosition.x + screenSize.x * (0.5 - 0.25 / 2), screenPosition.y + screenSize.y * 0.87, screenSize.x * 0.25, screenSize.y * 0.08)) then -- go back and save
  1745.             goBackToPanelCameFrom();
  1746.         elseif (isCursorOnRectangle(screenPosition.x + 5, screenPosition.y + screenSize.y / 2 - 13 / 2, 8, 13)) then -- go to the left
  1747.             phoneData.settings.wallpaper = math.max(0, phoneData.settings.wallpaper - 1);
  1748.  
  1749.         elseif (isCursorOnRectangle(screenPosition.x + screenSize.x - 5 - 8, screenPosition.y + screenSize.y / 2 - 13 / 2, 8, 13)) then
  1750.             if (File.exists("files/textures/wallpapers/" .. (phoneData.settings.wallpaper + 1) .. ".png")) then
  1751.                 phoneData.settings.wallpaper = phoneData.settings.wallpaper + 1;
  1752.             end
  1753.         end
  1754.     end
  1755. }
  1756.  
  1757. function math.clamp(val, min, max)
  1758.     return (val < min and min) or (val > max and max) or val;
  1759. end
  1760.  
  1761. -- utilty
  1762.  
  1763. function callNumber(number)
  1764.     local contact = getContactFromNumber(number);
  1765.     callInfo = {
  1766.         calledNumber = number,
  1767.         callerNumber = phoneData.number,
  1768.         callerPlayer = localPlayer,
  1769.         displayedNumberOrName = contact and contact.name or number,
  1770.         state = CALL_STATE.CALLING
  1771.     }
  1772.     setCurrentPanel(PANEL.CALL_OUTGOING);
  1773.     triggerServerEvent("onPlayerPhoneCall", localPlayer, number);
  1774. end
  1775.  
  1776. function setSMSSound(val)
  1777.     local prev = phoneData.settings.smsSound;
  1778.     if (File.exists("files/sounds/sms/" .. val .. ".mp3")) then phoneData.settings.smsSound = val; end
  1779.     return prev ~= phoneData.settings.smsSound;
  1780. end
  1781.  
  1782. function setRingtone(val)
  1783.     local prev = phoneData.settings.ringtone;
  1784.     if (File.exists("files/sounds/ringtone/" .. val .. ".mp3")) then phoneData.settings.ringtone = val; end
  1785.     return prev ~= phoneData.settings.ringtone;
  1786. end
  1787.  
  1788. function playRingtoneSound(phoneNumber, endAfter, loop, soundID, volume)
  1789.     local phoneNumber = phoneNumber or phoneData.number;
  1790.  
  1791.     if (isElement(soundElementsByPhone[phoneNumber].ringtone)) then soundElementsByPhone[phoneNumber].ringtone:destroy(); end
  1792.  
  1793.     local soundID = soundID or phoneData.settings.ringtone;
  1794.     local volume = volume or phoneData.settings.ringtoneVolume;
  1795.  
  1796.     local filePath = "files/sounds/ringtone/" .. soundID .. ".mp3"
  1797.     if (not File.exists(filePath)) then filePath = "files/sounds/ringtone/0.mp3"; end
  1798.    
  1799.     soundElementsByPhone[phoneNumber].ringtone = Sound(filePath, loop);
  1800.     soundElementsByPhone[phoneNumber].ringtone:setVolume(volume / 100);
  1801.  
  1802.     if (endAfter) then
  1803.         setTimer(
  1804.             function(n)
  1805.                 if (isElement(soundElementsByPhone[n].ringtone)) then
  1806.                     soundElementsByPhone[n].ringtone:destroy()
  1807.                     soundElementsByPhone[n] = nil;
  1808.                 end
  1809.             end,
  1810.         endAfter * 1000, 1, phoneNumber);
  1811.     end
  1812. end
  1813.  
  1814. function playSMSSound(phoneNumber, soundID, volume)
  1815.     outputConsole("call: " .. debug.traceback())
  1816.  
  1817.     local phoneNumber = phoneNumber or phoneData.number;
  1818.  
  1819.     local soundID = soundID or phoneData and phoneData.settings.smsSound;
  1820.     local volume = volume or phoneData and phoneData.settings.smsSoundVolume;
  1821.  
  1822.     local filePath = "files/sounds/sms/" .. soundID .. ".mp3"
  1823.     if (not File.exists(filePath)) then filePath = "files/sounds/sms/0.mp3"; end
  1824.    
  1825.     soundElementsByPhone[phoneNumber].sms = Sound(filePath);
  1826.     soundElementsByPhone[phoneNumber].sms:setVolume(volume / 100);
  1827. end
  1828.  
  1829. function goBackToPanelCameFrom()
  1830.     local tbllen = #panelSetHistory;
  1831.     if (tbllen > 0) then
  1832.         setCurrentPanel(table.remove(panelSetHistory, tbllen), true);
  1833.         table.remove(panelSetHistory, tbllen); -- remove the newly inserted panel(the panel we came from) so we dont get a cycle
  1834.     end
  1835. end
  1836.  
  1837. -- some drawing shit
  1838. function drawContactTabBar()
  1839.     local tabBarWidth = screenSize.x * 0.95;
  1840.     local iconSize = tabBarWidth / 4;
  1841.    
  1842.     local icons = {
  1843.         {"files/textures/icons/contact_app/favorites.png", "Kedvencek", 1, currentPanelID == PANEL.CONTACT_FAVORITES and 0xFF007aff or 0xFF464646},
  1844.         {"files/textures/icons/contact_app/contacts.png", "Kapcsolatok", 1.52, currentPanelID == PANEL.CONTACTS and 0xFF007aff or 0xFF464646},
  1845.         {"files/textures/icons/contact_app/recents.png", "Előzmény", 1, currentPanelID == PANEL.CALL_HISTORY and 0xFF007aff or 0xFF464646},
  1846.         {"files/textures/icons/contact_app/keypadicon.png", "Gombok", 1, currentPanelID == PANEL.CALL_KEYPAD and 0xFF007aff or 0xFF464646},
  1847.     }
  1848.  
  1849.     for i = 1, 4 do
  1850.         local x = screenPosition.x + screenSize.x / 2 - tabBarWidth / 2 + (i - 1) * iconSize;
  1851.  
  1852.         local size = screenSize.x * 0.085;
  1853.         dxDrawImage(x + iconSize / 2 - size * icons[i][3] / 2, screenPosition.y + screenSize.y * 0.9, size * icons[i][3], size, icons[i][1], 0, 0, 0, icons[i][4]);
  1854.         dxDrawText(icons[i][2], x + iconSize / 2, screenPosition.y + screenSize.y * 0.9 + size + 2, x + iconSize / 2, 0, icons[i][4], 1, fonts.roboto_light[10], "center", "top");
  1855.     end
  1856.  
  1857. end
  1858.  
  1859. function handleContactTabBarClick()
  1860.     local tabBarWidth = screenSize.x * 0.95;
  1861.     local iconSize = tabBarWidth / 4;
  1862.     for i = 0, 3 do
  1863.         if (isCursorOnRectangle(screenPosition.x + screenSize.x / 2 - tabBarWidth / 2 + i * iconSize, screenPosition.y + screenSize.y * 0.9, iconSize, iconSize)) then
  1864.             setCurrentPanel(PANEL[(i == 0 and "CONTACT_FAVORITES") or (i == 1 and "CONTACTS") or (i == 2 and "CALL_HISTORY") or (i == 3 and "CALL_KEYPAD")]);
  1865.  
  1866.             return true;
  1867.         end
  1868.     end
  1869.  
  1870.     return false;
  1871. end
  1872.  
  1873. -- favorite contact handling
  1874. function removeFavoriteByContactID(contactID)
  1875.     for k, v in pairs(phoneData.favoriteContacts) do
  1876.         if (v.id == contactID) then
  1877.             -- reset scroll index so we dont go out of list
  1878.             if (panels[PANEL.CONTACT_FAVORITES].drawableContactCount) then
  1879.                 panels[PANEL.CONTACT_FAVORITES].scrollIndex = math.min(panels[PANEL.CONTACT_FAVORITES].scrollIndex, #phoneData.favoriteContacts - 1 - panels[PANEL.CONTACT_FAVORITES].drawableContactCount);
  1880.             end
  1881.             v.favorite = false;
  1882.             triggerServerEvent("onPlayerChangeContactFavoriteState", localPlayer, v.id, false);
  1883.             table.remove(phoneData.favoriteContacts, k);    
  1884.             sortFavoriteList();
  1885.             return;
  1886.         end
  1887.     end
  1888.     return nil;
  1889. end
  1890.  
  1891. function addFavoriteContact(contactID)
  1892.     local contact = getContactFromID(contactID);
  1893.     if (not contact) then return; end
  1894.     contact.favorite = true;
  1895.     table.insert(phoneData.favoriteContacts, contact);
  1896.  
  1897.     triggerServerEvent("onPlayerChangeContactFavoriteState", localPlayer, contactID, true);
  1898.  
  1899.     return true;
  1900. end
  1901.  
  1902. function sortFavoriteList(list)
  1903.     table.sort(phoneData.contacts,
  1904.         function(a, b)
  1905.             return string.upper(a.name) < string.upper(b.name);
  1906.         end
  1907.     );
  1908. end
  1909.  
  1910.  
  1911. -- contact handling
  1912. addEvent("onClientPlayerAddPhoneContact", true);
  1913. addEventHandler("onClientPlayerAddPhoneContact", localPlayer,
  1914.     function(contact)
  1915.         table.insert(phoneData.contacts, contact);
  1916.         sortContactList();
  1917.         refreshCallHistoryContactNames();
  1918.     end
  1919. );
  1920.  
  1921. function removeContactByID(id)
  1922.     local contact, k = getContactFromID(id);
  1923.     if (contact.favorite) then removeFavoriteByContactID(contact.id); end
  1924.     table.remove(phoneData.contacts, k);
  1925.     refreshCallHistoryContactNames();
  1926.     triggerServerEvent("onPlayerDeletePhoneContact", localPlayer, id);
  1927. end
  1928.  
  1929. function getContactFromID(id)
  1930.     for k, v in pairs(phoneData.contacts) do
  1931.         if (v.id == id) then
  1932.             return v, k;
  1933.         end
  1934.     end
  1935. end
  1936.  
  1937. function getContactFromNumber(number)
  1938.     local number = tonumber(number);
  1939.     for k, v in pairs(phoneData.contacts) do
  1940.         if (v.number == number) then
  1941.             return v, k;
  1942.         end
  1943.     end
  1944. end
  1945.  
  1946. function getContactFromName(name)
  1947.     for k, v in pairs(phoneData.contacts) do
  1948.         if (v.name == name) then
  1949.             return v, k;
  1950.         end
  1951.     end
  1952.    
  1953.     return nil;
  1954. end
  1955.  
  1956. function sortContactList(list)
  1957.     table.sort(phoneData.contacts,
  1958.         function(a, b)
  1959.             return string.upper(a.name) < string.upper(b.name);
  1960.         end
  1961.     );
  1962. end
  1963.  
  1964.  
  1965. -- call history
  1966. function refreshCallHistoryContactNames()
  1967.     if (currentPanelID ~= PANEL.CALL_HISTORY) then return; end
  1968.  
  1969.     for k, v in pairs(phoneData.callHistory) do
  1970.         v.contact = getContactFromNumber(v.number);
  1971.     end
  1972. end
  1973.  
  1974. function refreshCallHisotryDates()
  1975.     if (currentPanelID ~= PANEL.CALL_HISTORY) then return; end
  1976.  
  1977.     local currentDate = getRealTime();
  1978.     for _, v in pairs(phoneData.callHistory) do
  1979.         local callDate, callDateStr = getRealTime(v.timestamp), "";
  1980.  
  1981.         if (callDate.year == currentDate.year) then -- same year
  1982.             if (callDate.yearday == currentDate.yearday) then -- same day
  1983.                 if (callDate.hour == currentDate.hour) then -- same hour
  1984.                     callDateStr = ((currentDate.minute - callDate.minute)) .. " perce";
  1985.                 else
  1986.                     callDateStr = ((currentDate.hour - callDate.hour)) .. " órája";
  1987.                 end
  1988.                
  1989.             -- same week
  1990.             elseif (callDate.yearday - currentDate.yearday == 1) then -- yesterday
  1991.                 callDateStr = ("Tegnap, %2i:%2i"):format(callDate.hour, callDate.minute);
  1992.            
  1993.             elseif (callDate.yearday - currentDate.yearday == 1) then -- two days ago
  1994.                 callDateStr = ("Tegnapelőtt, %2i:%2i"):format(callDate.hour, callDate.minute);
  1995.  
  1996.             elseif (callDate.month == currentDate.month and (callDate.monthday - callDate.weekday) == (currentDate.monthday - currentDate.weekday)) then
  1997.                 callDateStr = ("%s, %2i:%2i"):format(WEEKDAY_NAMES[callDate.weekday], callDate.hour, callDate.minute);
  1998.  
  1999.             else
  2000.                 callDateStr = ("%s %i, %2i:%2i"):format(MONTH_NAMES[callDate.month], callDate.monthday, callDate.hour, callDate.minute);
  2001.             end
  2002.         else -- not same year
  2003.             callDateStr = ("%i. %s %i, %2i:%2i"):format(1900 + callDate.year, MONTH_NAMES[callDate.month], callDate.monthday, callDate.hour, callDate.minute);
  2004.         end
  2005.  
  2006.         v.text = HISOTRY_CALL_TYPE_TEXTS[v.type] .. " - " .. callDateStr;
  2007.     end
  2008. end
  2009.  
  2010.  
  2011. function getSMSArrayFromNumber(number)
  2012.     for k, v in pairs(phoneData.messages) do
  2013.         if (v.number == number) then
  2014.             return v, k;
  2015.         end
  2016.     end
  2017. end
  2018.  
  2019. function sortSMSArray()
  2020.     table.sort(phoneData.messages,
  2021.         function(a, b)
  2022.             return a[#a].timestamp > b[#b].timestamp;
  2023.         end
  2024.     );
  2025. end
  2026.  
  2027. addEvent("onClientPlayerUpdatePhoneBalance", true);
  2028. addEventHandler("onClientPlayerUpdatePhoneBalance", localPlayer,
  2029.     function(balance)
  2030.         phoneData.balance = balance;
  2031.     end
  2032. );
  2033.  
  2034. addEvent("onClientPlayerUsePhoneItem", true);
  2035. addEventHandler("onClientPlayerUsePhoneItem", localPlayer,
  2036.     function(state, data)
  2037.         setPhoneVisible(state, data);
  2038.     end
  2039. );
  2040.  
  2041. -- Call related
  2042. addEvent("onClientPlayerCallIncoming", true);
  2043. addEventHandler("onClientPlayerCallIncoming", localPlayer,
  2044.     function(callerNumber, calledNumber, ringtone, ringtoneVolume)
  2045.         -- if ringtone / ringtoneVolume vars are missing then the current phone's settings must be used.
  2046.  
  2047.         playRingtoneSound(calledNumber, nil, true, ringtone, ringtoneVolume);
  2048.        
  2049.         -- if no other phone is showing then just show the called phone.
  2050.         if (not isShowing) then
  2051.             exports.cr_inventory:findAndUseItemByIDAndValue(15, calledNumber);
  2052.  
  2053.         end
  2054.  
  2055.         if (calledNumber == phoneData.number) then
  2056.             local contact = getContactFromNumber(callerNumber);
  2057.             callInfo = {
  2058.                 callerNumber = callerNumber,
  2059.                 calledNumber = phoneData.number,
  2060.  
  2061.                 displayedNumberOrName = contact and contact.name or callerNumber,
  2062.  
  2063.                 state = CALL_STATE.CALL_INCOMING
  2064.             };
  2065.             setCurrentPanel(PANEL.CALL_INCOMING);
  2066.         end
  2067.     end
  2068. );
  2069.  
  2070. addEvent("onClientSetInCall", true); -- used to set player in call when he put away his phone while in call.
  2071. addEventHandler("onClientSetInCall", localPlayer,
  2072.     function(callerNumber, calledNumber, messages)
  2073.         assert(type(messages) == "table")
  2074.  
  2075.         local contact = getContactFromNumber(callerNumber == phoneData.number and calledNumber or callerNumber);
  2076.         callInfo = {
  2077.             callerNumber = callerNumber,
  2078.             calledNumber = calledNumber,
  2079.  
  2080.             displayedNumberOrName = contact and contact.name or callerNumber,
  2081.  
  2082.             state = CALL_STATE.TALKING
  2083.         };
  2084.         setCurrentPanel(PANEL.CALL_CHAT);
  2085.  
  2086.         panels[currentPanelID].addMessages(messages);
  2087.     end
  2088. );
  2089.  
  2090. addEvent("onClientPlayerCancelCall", true)
  2091. addEventHandler("onClientPlayerCancelCall", localPlayer,
  2092.     function(calledNumber, callerNumber, state, timestamp)        
  2093.         setTimer(
  2094.             function()
  2095.                 goBackToPanelCameFrom();
  2096.                 callInfo = {};
  2097.             end,
  2098.         2500, 1, PANEL.MENU);
  2099.  
  2100.         if (callerNumber == phoneData.number) then --
  2101.             addCallToHistory(calledNumber, HISTORY_CALL_TYPE.OUTGOING, timestamp);
  2102.            
  2103.         elseif (calledNumber == phoneData.number) then
  2104.             local histType = calledPhoneCallHistoryType or HISTORY_CALL_TYPE[callInfo.state == CALL_STATE.TALKING and "INCOMING" or "INCOMING_UNANSWERED"];
  2105.             addCallToHistory(callerNumber, histType, timestamp);
  2106.         end
  2107.  
  2108.         if (isElement(soundElementsByPhone[calledNumber].ringtone)) then soundElementsByPhone[calledNumber].ringtone:destroy();  end
  2109.  
  2110.         callInfo.state = state or CALL_STATE[(callInfo.state == CALL_STATE.TALKING or callInfo.state == CALL_STATE.INCOMING) and "CALL_ENDED" or "LINE_BUSY"];
  2111.     end
  2112. );
  2113.  
  2114. addEvent("onClientPlayerAcceptCall", true)
  2115. addEventHandler("onClientPlayerAcceptCall", localPlayer,
  2116.     function()
  2117.         callInfo.state = CALL_STATE.TALKING;
  2118.         setCurrentPanel(PANEL.CALL_CHAT);
  2119.         if (isElement(soundElementsByPhone[phoneData.number].ringtone)) then soundElementsByPhone[phoneData.number].ringtone:destroy(); end
  2120.     end
  2121. );
  2122.  
  2123. addEvent("onClientPlayerReceiveCallChatMessage", true);
  2124. addEventHandler("onClientPlayerReceiveCallChatMessage", localPlayer,
  2125.     function(msg)
  2126.         panels[PANEL.CALL_CHAT].addMessage("other", msg);
  2127.     end
  2128. );
  2129.  
  2130.  
  2131. addEvent("onPhoneAddCallToHistory", true);
  2132. function addCallToHistory(number, historyType, timestamp)
  2133.     table.insert(phoneData.callHistory, 1, {
  2134.         number = number,
  2135.         timestamp = getRealTime().timestamp,
  2136.         type = historyType or HISTORY_CALL_TYPE.OUTGOING
  2137.     });
  2138. end
  2139. addEventHandler("onPhoneAddCallToHistory", localPlayer, addCallToHistory);
  2140.  
  2141. -- SMS
  2142.  
  2143. -- receives all messages with a speificed partner
  2144. addEvent("onClientServerSendPhoneMessages", true);
  2145. addEventHandler("onClientServerSendPhoneMessages", localPlayer,
  2146.     function(number, messages)
  2147.         outputConsole("got messages\n"..inspect(messages))
  2148.  
  2149.         local _, k = getSMSArrayFromNumber(number);
  2150.         if (not k) then table.insert(phoneData.messages, 1, {}); k = 1; end
  2151.  
  2152.         if (currentPanelID == PANEL.CONTACT_MESSENGER) then
  2153.             panels[currentPanelID].clear();
  2154.             for k, v in pairs(messages) do
  2155.                 assert(type(v) == "table", "v not table @ "..k)
  2156.                 panels[currentPanelID].addMessage(v.isSender and "me" or "other", v.text, v.state);
  2157.             end
  2158.         end
  2159.  
  2160.         phoneData.messages[k] = messages;
  2161.         phoneData.messages[k].number = number;
  2162.     end
  2163. );
  2164.  
  2165. -- only called if the current phone is the phone that got the SMS
  2166. addEvent("onClientPlayerRecieveSMS", true);
  2167. addEventHandler("onClientPlayerRecieveSMS", localPlayer,
  2168.     function(sentBy, sentTo, messageData, smsSoundID, volume)
  2169.         playSMSSound(sentToNumber, smsSoundID, volume);
  2170.  
  2171.         if (phoneData.number == sentTo) then
  2172.             local smss, k = getSMSArrayFromNumber(sentBy);
  2173.             if (not k) then table.insert(phoneData.messages, 1, {number = sentBy}); k = 1; end
  2174.             table.insert(smss, messageData);
  2175.  
  2176.             table.move(phoneData.messages, k, 1); -- move this SMS to the first place, because this is the latest one.
  2177.  
  2178.             if ((currentPanelID == PANEL.CONTACT_MESSENGER) and (panels[currentPanelID].phoneNumber == sentBy)) then
  2179.                 panels[PANEL.CONTACT_MESSENGER].addMessage("other", messageData.text);
  2180.             end
  2181.         end
  2182.     end
  2183. );
  2184.  
  2185. addEvent("onServerConfirmSMSSend", true);
  2186. addEventHandler("onServerConfirmSMSSend", localPlayer,
  2187.     function(sentBy, sentTo, messageData) --senderPhone.number, message, sendToPhoneNumber, SMS_STATE.FAILED_TO_SEND_INVALID_NUMBER
  2188.         if (phoneData.number == sentBy) then
  2189.             local smss, k = getSMSArrayFromNumber(sentTo);
  2190.             table.insert(smss, 1, messageData);
  2191.  
  2192.             table.move(phoneData.messages, k, 1); -- move this SMS to the first place, because this is the latest one.
  2193.  
  2194.             if ((currentPanelID == PANEL.CONTACT_MESSENGER) and (panels[currentPanelID].phoneNumber == sentTo)) then
  2195.                 panels[PANEL.CONTACT_MESSENGER].addMessage("me", messageData.text);
  2196.             end
  2197.         end
  2198.     end
  2199. );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement