diff --git a/Libs/DF/definitions.lua b/Libs/DF/definitions.lua index bf5eb2fb9..980a6b2e8 100644 --- a/Libs/DF/definitions.lua +++ b/Libs/DF/definitions.lua @@ -324,6 +324,7 @@ ---@field GetAsianNumberSymbols fun(self:table) : string, string, string return the abbreviation for 1,000 10,000 and 100,000,000 ---@field GetBestFontForLanguage fun(self:table, languageId:string?, western:string?, cyrillic:string?, china:string?, korean:string?, taiwan:string?) : string ---@field CreateGlowOverlay fun(self:table, parent:frame, antsColor:any, glowColor:any) : frame +---@field CreateSimpleFrame fun(self:table, parent:frame, width:number?, height:number?, title:string?, frameName:string?, panelOptions:table?, savedVariableTable:table?) : simplepanel ---@field CreateAnts fun(self:table, parent:frame, antTable:df_anttable, leftOffset:number?, rightOffset:number?, topOffset:number?, bottomOffset:number?) : frame ---@field CreateBorder fun(self:table, parent:frame, alpha1:number?, alpha2:number?, alpha3:number?) : frame ---@field CreateMenuWithGridScrollBox fun(self:table, parent:frame, name:string?, refreshMeFunc:function, refreshButtonFunc:function, clickFunc:function, onCreateButton:function, gridScrollBoxOptions:df_gridscrollbox_options) : df_gridscrollbox create a scrollbox with a grid layout to be used as a menu diff --git a/Libs/DF/panel.lua b/Libs/DF/panel.lua index d60bd7bc8..b91b8539a 100644 --- a/Libs/DF/panel.lua +++ b/Libs/DF/panel.lua @@ -2141,6 +2141,7 @@ local no_options = {} ---@field Title fontstring ---@field Close button ---@field SetTitle fun(self: simplepanel, title: string) + ---@param parent frame the parent frame ---@param width number? the width of the panel ---@param height number? the height of the panel @@ -2148,7 +2149,7 @@ local no_options = {} ---@param frameName string? the name of the frame ---@param panelOptions table? a table with options described above ---@param savedVariableTable table? a table to save the scale of the panel ----@return frame +---@return simplepanel function detailsFramework:CreateSimplePanel(parent, width, height, title, frameName, panelOptions, savedVariableTable) --create a saved variable table if the savedVariableTable has been not passed within the function call if (savedVariableTable and frameName and not savedVariableTable[frameName]) then diff --git a/boot.lua b/boot.lua index f78420c95..d094e9b95 100644 --- a/boot.lua +++ b/boot.lua @@ -19,12 +19,12 @@ local addonName, Details222 = ... local version, build, date, tvs = GetBuildInfo() - Details.build_counter = 13001 - Details.alpha_build_counter = 13001 --if this is higher than the regular counter, use it instead + Details.build_counter = 13009 + Details.alpha_build_counter = 13009 --if this is higher than the regular counter, use it instead Details.dont_open_news = true Details.game_version = version Details.userversion = version .. " " .. Details.build_counter - Details.realversion = 160 --core version, this is used to check API version for scripts and plugins (see alias below) + Details.realversion = 161 --core version, this is used to check API version for scripts and plugins (see alias below) Details.gametoc = tvs Details.APIVersion = Details.realversion --core version Details.version = Details.userversion .. " (core " .. Details.realversion .. ")" --simple stirng to show to players diff --git a/functions/slash.lua b/functions/slash.lua index a08935b8e..bc7f40ced 100644 --- a/functions/slash.lua +++ b/functions/slash.lua @@ -2575,7 +2575,6 @@ local canAcceptNoteOn = { noteEditor.OpenNoteOptionsPanel = function() if (not DetailsNoteOptionsFrame) then local mainFrame = detailsFramework:CreateSimplePanel(UIParent, 600, 400, "Notes (/note) Options", "DetailsNoteOptionsFrame") - mainFrame:SetPoint("center", UIParent, "center", -200, 0) detailsFramework:ApplyStandardBackdrop(mainFrame) --dont allow the mainframe go off screen mainFrame:SetClampedToScreen(true) @@ -2872,11 +2871,123 @@ noteEditor.OpenNoteOptionsPanel = function() local invalidCommId = "" local bIsSimulateOnClient = true noteEditor.OpenNoteScreenPanel(UnitName("player"), testText, invalidCommId, bIsSimulateOnClient) + screenFrame = DetailsNoteScreenFrame end + DetailsNoteOptionsFrame:ClearAllPoints() + + DetailsNoteOptionsFrame:SetPoint("left", screenFrame, "right", 50, 0) DetailsNoteOptionsFrame:Show() end +--this is a function which open a frame with a text entry with text telling about the api of the note feature +local openAPIFrame = function() + local CONST_WINDOW_WIDTH = 614 + local CONST_WINDOW_HEIGHT = 720 + local editorAlpha = 0.1 + + local mainFrame = detailsFramework:CreateSimplePanel(UIParent, CONST_WINDOW_WIDTH, CONST_WINDOW_HEIGHT, "Notes (/note) API", "DetailsNoteAPIFrame") + mainFrame:SetPoint("left", UIParent, "left", 50, 0) + mainFrame:SetToplevel(true) + + --create a lua text entry to show the api text + local editboxNotes = detailsFramework:NewSpecialLuaEditorEntry(mainFrame, CONST_WINDOW_WIDTH - 10, CONST_WINDOW_HEIGHT - 30, "editboxNotes", "$parentAPIEditbox", true) + editboxNotes:SetPoint("topleft", mainFrame, "topleft", 2, -25) + editboxNotes:SetBackdrop(nil) + detailsFramework:ReskinSlider(editboxNotes.scroll) + mainFrame.EditboxNotes = editboxNotes + + editboxNotes.scroll:ClearAllPoints() + editboxNotes.scroll:SetPoint("topleft", editboxNotes, "topleft", 1, -1) + editboxNotes.scroll:SetPoint("bottomright", editboxNotes, "bottomright", -1, 0) + + local font, h, flags = editboxNotes.editbox:GetFont() + editboxNotes.editbox:SetFont(font, 12, flags) + editboxNotes.editbox:SetAllPoints() + editboxNotes.editbox:SetBackdrop(nil) + editboxNotes.editbox:SetTextInsets(4, 4, 4, 4) + + local CONST_EDITBOX_COLOR = {.6, .6, .6, .5} + local rr, gg, bb = unpack(CONST_EDITBOX_COLOR) + local backgroundTexture1 = editboxNotes.scroll:CreateTexture(nil, "background", nil, -6) + backgroundTexture1:SetAllPoints() + backgroundTexture1:SetColorTexture(rr, gg, bb, editorAlpha) + + local backgroundTexture2 = editboxNotes.editbox:CreateTexture(nil, "background", nil, -6) + backgroundTexture2:SetAllPoints() + backgroundTexture2:SetColorTexture(rr, gg, bb, editorAlpha) + + local backgroundTexture3 = editboxNotes:CreateTexture(nil, "background", nil, -6) + backgroundTexture3:SetAllPoints() + backgroundTexture3:SetColorTexture(0, 0, 0, 1) + + editboxNotes.backgroundTexture1 = backgroundTexture1 + editboxNotes.backgroundTexture2 = backgroundTexture2 + editboxNotes.backgroundTexture3 = backgroundTexture3 + + editboxNotes:SetText([[ +Open Raid API: + +- Notes sent using OpenRaid are logged on the server so players can be reported. Check the report code on details/functions/slash.lua +- OpenRaid will error if the note has less than 50 characters or more than 1500 characters. + +---@alias playername string + +---@class unitnote : table +---@field note string +---@field commId string + +--register a callback to receive notes sent by other players: +local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true) +if (openRaidLib) then + local anObject = { + ---@param unitId string who sent the note + ---@param unitNote unitnote the note object + ---@param allUnitsNote table<playername, unitnote> a table containing all notes sent by all players + OnNoteUpdate = function(unitId, unitNote, allUnitsNote) + --unitNote.note is the note + --unitNote.commId is the communication id used at the report player dialog + + if (unitNote.commId:len() < 8) then + --there was a problem registering the note on the server, and the note should be discarded. + return + end + end + } + openRaidLib.RegisterCallback(anObject, "NoteUpdated", "OnNoteUpdate") +end + +--send a note to other player in the group: +local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true) +if (openRaidLib) then + local noteText = "Hello, I'm sending a note to the group!, how are you?" + --tell OpenRaid that the note of this player is noteText + openRaidLib.SetPlayerNote(noteText) + --tell OpenRaid to send the note set by the player to all other players in the group + openRaidLib.SendPlayerNote() +end + + +Details API: + +- Each once of the slashes /note /notes /notepad can be replaced by an addon to handle the note feature, use: + +---@alias notecommand +---| "NOTE" +---| "NOTES" +---| "NOTEPAD" + +---@param addonObject table a table containing the function to be called, example: {[memberName] = function()end} +---@param memberName string a function name that exists inside the addonObject table +---@param noteCommandToReplace notecommand which note command to replace +---@param ... any any number of parameters to be passed to the callback function +---@return boolean bGotRegistered true if the addon was registered, false if it was already registered and got unregistered +Details:ReplaceNoteCommand(addonObject, memberName, noteCommandToReplace, ...) + +]]) +end + + ---@param unitIds unit[] ---@return unit[], unit[], unit[] function noteEditor.PrepareUnitRoleTables(unitIds) @@ -2990,6 +3101,12 @@ function noteEditor.ParseNoteText(text, bNoColoring) end noteEditor.OpenNoteEditor = function() + --check if the client is running retail version + if (not detailsFramework.IsDragonflightAndBeyond()) then + Details:Msg("This feature is only available on retail version.") + return + end + local openRaidLib = LibStub:GetLibrary("LibOpenRaid-1.0", true) if (openRaidLib) then if (not DetailsNoteFrame) then @@ -3225,6 +3342,7 @@ noteEditor.OpenNoteEditor = function() local createNewPlayerSelectionButton = function() local newButton = detailsFramework:CreateButton(bottomFrameFloating, function()end, 100, 22, "") + detailsFramework:CreateHighlightTexture(newButton) return newButton end @@ -3494,10 +3612,15 @@ noteEditor.OpenNoteEditor = function() detailsFramework:ApplyStandardBackdrop(bottomFrame) mainFrame.BottomFrame = bottomFrame + local buttonWidth = 136 + local buttonHeight = 22 + local sendButton = detailsFramework:CreateButton(bottomFrame, function() local noteText = mainFrame.EditboxNotes.editbox:GetText() if (noteText:len() < CONST_NOTE_MIN_CHARACTERS) then - Details:Msg("Note is too short, must have at least " .. CONST_NOTE_MIN_CHARACTERS .. " characters.") + local msg = "Note is too short, must have at least " .. CONST_NOTE_MIN_CHARACTERS .. " characters." + Details:Msg(msg) + mainFrame.ShowErrorMsg(msg) return end @@ -3521,7 +3644,9 @@ noteEditor.OpenNoteEditor = function() --open raid do not send the note to the local player, need to trigger the screen panel manually local zoneName, instanceType, difficultyID, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID, instanceGroupSize = GetInstanceInfo() if (not canAcceptNoteOn[difficultyID] and not Details.debug) then --at the moment, players can only receive notes if inside a mythic dungeon - Details:Msg("At the moment, you can only send and receive notes inside a mythic dungeon.") + local msg = "At the moment, you can only send and receive notes inside a mythic dungeon." + Details:Msg(msg) + mainFrame.ShowErrorMsg(msg) return end @@ -3530,7 +3655,7 @@ noteEditor.OpenNoteEditor = function() local bIsSimulateOnClient = true noteEditor.OpenNoteScreenPanel(UnitName("player"), noteText, "", bIsSimulateOnClient) - end, 140, 22, "Send Note") + end, buttonWidth, buttonHeight, "Send Note") sendButton:SetPoint("topleft", bottomFrame, "topleft", 0, -2) sendButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")) sendButton:SetIcon("Interface\\BUTTONS\\JumpUpArrow", 18, 18, "overlay", {0, 1, 0, 1}) @@ -3538,7 +3663,7 @@ noteEditor.OpenNoteEditor = function() local saveNoteButton = detailsFramework:CreateButton(bottomFrame, function() mainFrame.SaveNote(mainFrame.currentNoteIndex) - end, 140, 22, "Save Note") + end, buttonWidth, buttonHeight, "Save Note") saveNoteButton:SetPoint("bottomleft", sendButton, "bottomright", 4, 0) saveNoteButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")) saveNoteButton:SetIcon([[Interface\BUTTONS\UI-GuildButton-PublicNote-Up]], 16, 16, "overlay") @@ -3547,7 +3672,7 @@ noteEditor.OpenNoteEditor = function() local newNoteButton = detailsFramework:CreateButton(bottomFrame, function() mainFrame.CreateEmptyNote() - end, 140, 22, "New Empty Note") + end, buttonWidth, buttonHeight, "New Empty Note") newNoteButton:SetPoint("bottomleft", saveNoteButton, "bottomright", 4, 0) newNoteButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")) newNoteButton:SetIcon([[Interface\BUTTONS\UI-GuildButton-PublicNote-Up]], 16, 16, "overlay") @@ -3556,13 +3681,59 @@ noteEditor.OpenNoteEditor = function() local optionsButton = detailsFramework:CreateButton(bottomFrame, function() noteEditor.OpenNoteOptionsPanel() - end, 140, 22, "OPTIONS") + end, buttonWidth, buttonHeight, "OPTIONS") optionsButton:SetPoint("bottomleft", newNoteButton, "bottomright", 4, 0) optionsButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")) optionsButton:SetIcon([[Interface\Scenarios\ScenarioIcon-Interact]], 16, 16, "overlay") optionsButton:SetAlpha(1) detailsFramework:CreateHighlightTexture(optionsButton) + local apiButton = detailsFramework:CreateButton(bottomFrame, function() + openAPIFrame() + end, 50, buttonHeight, "API") + apiButton:SetPoint("bottomleft", optionsButton, "bottomright", 4, 0) + apiButton:SetTemplate(detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE")) + apiButton:SetAlpha(1) + detailsFramework:CreateHighlightTexture(apiButton) + + --error msg fontstring, this text is used to show errors to the user, its color is red, size 13 and it is placed centered and below the buttons above + --it also has an animation to fade out after 5 seconds, and a shake animation when it's shown + local errorMsg = bottomFrame:CreateFontString(nil, "overlay", "GameFontNormal") + errorMsg:SetPoint("top", bottomFrame, "top", 0, (buttonHeight + 14) * -1) + errorMsg:SetWidth(bottomFrame:GetWidth() - 10) + errorMsg:SetJustifyH("center") + errorMsg:SetAlpha(0) + detailsFramework:SetFontColor(errorMsg, "orangered") + detailsFramework:SetFontSize(errorMsg, 13) + mainFrame.ErrorMsg = errorMsg + + --fade out animation using details framework animation hub + local fadeOutAnimationHub = detailsFramework:CreateAnimationHub(errorMsg, function()end, function() errorMsg:SetAlpha(0) end) + detailsFramework:CreateAnimation(fadeOutAnimationHub, "Alpha", 1, 2, 1, 0) + + --fade in animation using details framework animation hub + local fadeInAnimationHub = detailsFramework:CreateAnimationHub(errorMsg, function() errorMsg:SetAlpha(0) end, function() errorMsg:SetAlpha(1) end) + detailsFramework:CreateAnimation(fadeInAnimationHub, "Alpha", 1, 0.1, 0, 1) + + --shake animation using details framework + local shake = detailsFramework:CreateFrameShake(errorMsg, 0.4, 6, 20, false, true, 0, 1, 0, 0.3) + + function mainFrame.ShowErrorMsg(msg) + fadeInAnimationHub:Play() + mainFrame.ErrorMsg:SetText(msg) + mainFrame.ErrorMsg:PlayFrameShake(shake) + + if (errorMsg.HideTimer) then + return + end + + errorMsg.HideTimer = C_Timer.NewTimer(4, function() + fadeOutAnimationHub:Play() + errorMsg.HideTimer = nil + end) + end + + --create a texture of size 16 16 with the texture [[Interface\BUTTONS\UI-SliderBar-Button-Vertical]], the point is the same as the whats this text local whatsThisIcon = bottomFrame:CreateTexture(nil, "overlay") whatsThisIcon:SetTexture([[Interface\BUTTONS\UI-SliderBar-Button-Vertical]]) @@ -3652,6 +3823,7 @@ noteEditor.OpenNoteScreenPanel = function(senderName, noteText, commId, bIsSimul detailsFramework:AddRoundedCornersToFrame(screenFrame, Details.PlayerBreakdown.RoundedCornerPreset) local red, green, blue = detailsFramework:GetDefaultBackdropColor() screenFrame:SetColor(red, green, blue, 0.98) + screenFrame:SetClampedToScreen(true) local rightClickFrame = CreateFrame("button", "$parentRightClickFrame", screenFrame) rightClickFrame:SetAllPoints() @@ -4061,4 +4233,9 @@ C_Timer.After(0, function() SubscriptionInterstitialFrame.ClosePanelButton:Click() end end -end) \ No newline at end of file +end) + + + + +