mirror of
https://github.com/Lacustat/Freewood-OctoWoW-Mail.git
synced 2026-10-30 23:37:01 +00:00
0.1.159: Brett-Brief ueber den Freewood-Briefkasten (sichtbar, Auto-Senden), dynamisches Sendetempo, Betreff so breit wie Text
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016onJCSHLwhs9udhC9ZLzk9
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
## Notes: Own mailbox window: open all or selected mails safely, recent recipients, mailing lists with automatic sending, multi-item mails, gold surplus and cash on delivery.
|
||||
## Notes-deDE: Eigenes Briefkasten-Fenster: alles oder Ausgewähltes sicher öffnen, letzte Empfänger, Mailinglisten mit Automatik, mehrere Items, Gold-Überschuss und Nachnahme.
|
||||
## Author: Lacustat
|
||||
## Version: 0.1.158
|
||||
## Version: 0.1.159
|
||||
## Dependencies: Freewood-OctoWoW-Core
|
||||
## OptionalDeps: Freewood-OctoWoW-Creator, Freewood-OctoWoW-Brett
|
||||
|
||||
|
||||
+20
@@ -56,6 +56,16 @@ FW:AddLocale("enUS", {
|
||||
MAIL_SEND_COD_NEEDS_ITEM = "Cash on delivery needs at least one item.",
|
||||
MAIL_BOARD_BUSY = "A board mission is preparing a mail. Finish it in the mission window first; this window waits.",
|
||||
MAIL_BUSY = "Another action is running. Please wait.",
|
||||
MAIL_BOARD_TITLE = "Board mission letter",
|
||||
MAIL_BOARD_FILLING = "The letter is being prepared ...",
|
||||
MAIL_BOARD_READY_AUTO = "Everything is correct. The letter is sent automatically.",
|
||||
MAIL_BOARD_READY_MANUAL = "Everything is correct. Click \"Send now\".",
|
||||
MAIL_BOARD_LOCKED = "The letter was changed and is locked. Close the mailbox and open it again.",
|
||||
MAIL_BOARD_SEND = "Send now",
|
||||
MAIL_BOARD_ADD = "Add what is missing",
|
||||
MAIL_BOARD_SENT = "Board letter sent.",
|
||||
MAIL_SPEED_ADAPT = "Mailbox: the server is slowing down, the sending speed was adapted.",
|
||||
MAIL_SET_BOARDAUTO = "Send board mission letters automatically once everything is correct",
|
||||
|
||||
MAIL_PICK_TITLE = "Choose items",
|
||||
MAIL_PICK_LIST_TITLE = "Items for %s",
|
||||
@@ -196,6 +206,16 @@ FW:AddLocale("deDE", {
|
||||
MAIL_SEND_COD_NEEDS_ITEM = "Nachnahme braucht mindestens ein Item.",
|
||||
MAIL_BOARD_BUSY = "Ein Brett-Auftrag bereitet gerade einen Brief vor. Erst im Auftragsfenster abschließen; dieses Fenster wartet.",
|
||||
MAIL_BUSY = "Es läuft gerade eine andere Aktion. Bitte warten.",
|
||||
MAIL_BOARD_TITLE = "Brief für einen Brett-Auftrag",
|
||||
MAIL_BOARD_FILLING = "Der Brief wird vorbereitet ...",
|
||||
MAIL_BOARD_READY_AUTO = "Alles stimmt. Der Brief wird automatisch gesendet.",
|
||||
MAIL_BOARD_READY_MANUAL = "Alles stimmt. Klicke auf \"Jetzt senden\".",
|
||||
MAIL_BOARD_LOCKED = "Der Brief wurde verändert und ist gesperrt. Briefkasten schließen und neu öffnen.",
|
||||
MAIL_BOARD_SEND = "Jetzt senden",
|
||||
MAIL_BOARD_ADD = "Fehlendes ergänzen",
|
||||
MAIL_BOARD_SENT = "Brett-Brief gesendet.",
|
||||
MAIL_SPEED_ADAPT = "Briefkasten: Der Server bremst, das Sendetempo wurde angepasst.",
|
||||
MAIL_SET_BOARDAUTO = "Brett-Auftragsbriefe automatisch senden, sobald alles stimmt",
|
||||
|
||||
MAIL_PICK_TITLE = "Items auswählen",
|
||||
MAIL_PICK_LIST_TITLE = "Items für %s",
|
||||
|
||||
@@ -29,7 +29,10 @@ local MAX_JOBS = 120
|
||||
local STEP = 0.1 -- Takt des Treibers
|
||||
local INBOX_GAP = 0.5 -- Pause nach dem Nehmen
|
||||
local INBOX_TIMEOUT = 2.5 -- so lange auf die Antwort des Servers warten
|
||||
local SEND_GAP = 1.2 -- Pause nach jedem gesendeten Brief
|
||||
local GAP_START = 0.4 -- Pause nach jedem gesendeten Brief: Start, wird dynamisch angepasst
|
||||
local GAP_MIN = 0.25
|
||||
local GAP_MAX = 4
|
||||
local MAX_RETRY = 3 -- so oft wird ein vom Server abgelehnter Brief mit langsamerem Tempo wiederholt
|
||||
local SEND_TIMEOUT = 8
|
||||
local POSTAGE = 30 -- Kupfer je Brief (Schaetzung fuer den Gold-Ueberschuss)
|
||||
local AUTO_DELAY = 2.5
|
||||
@@ -51,7 +54,7 @@ local Mail = FW:NewModule("Mail", {
|
||||
title = L.MAIL_TITLE,
|
||||
description = L.MAIL_DESC,
|
||||
defaults = {
|
||||
settings = { replace = false, chat = true, cleanup = true, archiveDays = 0 },
|
||||
settings = { replace = false, chat = true, cleanup = true, archiveDays = 0, boardAuto = true },
|
||||
recipients = {},
|
||||
lists = {},
|
||||
archive = {}, -- entfernte Briefe, neueste zuerst
|
||||
@@ -64,6 +67,7 @@ FW.Mail = Mail
|
||||
Mail.open = false -- ein Briefkasten ist offen
|
||||
Mail.busy = nil -- nil | "inbox" | "send"
|
||||
Mail.gen = 0 -- zaehlt die Briefkasten-Oeffnungen
|
||||
Mail.gap = GAP_START -- aktuelle Pause zwischen zwei Briefen (so klein wie moeglich, waechst bei Ablehnung)
|
||||
|
||||
local function Now() return GetTime and GetTime() or 0 end
|
||||
local function After(t, fn)
|
||||
@@ -360,6 +364,46 @@ function Mail:RemoveMail(m)
|
||||
return true, own and "own" or "archived"
|
||||
end
|
||||
|
||||
-- Brett-Brief: Ein Brett-Auftrag bereitet einen Brief vor (Creator befuellt das verdeckte Briefformular).
|
||||
-- Mit ersetztem Briefkasten zeigt unser Fenster den Stand und sendet selbst, sobald alles stimmt.
|
||||
function Mail.BoardLetter()
|
||||
local C = FW.Creator
|
||||
if not (C and C.GuardState and C.MailCheck) then return nil end
|
||||
local ok, st = pcall(C.GuardState)
|
||||
if not ok or not st or st == "off" then return nil end
|
||||
local ok2, list, all = pcall(C.MailCheck)
|
||||
if not ok2 then list, all = nil, false end
|
||||
return { state = st, list = list or {}, all = all and true or false }
|
||||
end
|
||||
|
||||
function Mail:BoardSend()
|
||||
local bl = Mail.BoardLetter()
|
||||
if not bl or bl.state ~= "armed" or not bl.all then return false end
|
||||
local b = _G.SendMailMailButton
|
||||
if not (b and b.Click) then return false end
|
||||
if b.IsEnabled and not b:IsEnabled() then return false end
|
||||
self.boardSending = true
|
||||
Trace("Brett-Brief: Senden ueber den Freewood-Briefkasten")
|
||||
pcall(b.Click, b)
|
||||
return true
|
||||
end
|
||||
|
||||
-- Automatisch senden, wenn alles stimmt (Einstellung "boardAuto"), hoechstens 3 Versuche je Oeffnung
|
||||
function Mail:BoardAuto()
|
||||
if not (self.open and self.Replacing() and self.db.settings.boardAuto) then return end
|
||||
if self.boardAutoAt or (self.boardTries or 0) >= 3 then return end
|
||||
local bl = Mail.BoardLetter()
|
||||
if not bl or bl.state ~= "armed" or not bl.all then return end
|
||||
self.boardAutoAt = true
|
||||
After(0.8, function()
|
||||
Mail.boardAutoAt = nil
|
||||
if Mail.open and Mail.Replacing() then
|
||||
Mail.boardTries = (Mail.boardTries or 0) + 1
|
||||
Mail:BoardSend()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Brief an den Absender zurueckschicken (Anhang und Gold gehen mit zurueck). Nicht moeglich bei System-/Auktionsbriefen.
|
||||
function Mail.Returnable(m)
|
||||
if not m or not m.canReply or m.returned then return false end
|
||||
@@ -647,9 +691,24 @@ function Mail:StepSend()
|
||||
if Mail.BoardBusy() then return self:FinishSend("board") end
|
||||
if s.stage == "wait" then
|
||||
if s.ok then
|
||||
s.stage, s.nextAt = "next", now + SEND_GAP
|
||||
-- Erfolg: Tempo langsam wieder erhoehen (Pause kleiner), solange der Server mitkommt
|
||||
s.streak = (s.streak or 0) + 1
|
||||
if s.streak >= 3 then s.streak = 0 Mail.gap = math.max(GAP_MIN, Mail.gap * 0.8) end
|
||||
s.retry = 0
|
||||
s.stage, s.nextAt = "next", now + Mail.gap
|
||||
elseif s.err then
|
||||
return self:FinishSend("error")
|
||||
-- Der Server hat den Brief abgelehnt (meist zu schnell): Pause verdoppeln und denselben Brief nochmal versuchen
|
||||
s.retry = (s.retry or 0) + 1
|
||||
if s.retry > MAX_RETRY then return self:FinishSend("error") end
|
||||
s.streak = 0
|
||||
Mail.gap = math.min(GAP_MAX, Mail.gap * 2 + 0.3)
|
||||
Trace(string.format("Server lehnt ab: Pause jetzt %.2f s, Versuch %d von %d fuer Brief %d", Mail.gap, s.retry, MAX_RETRY, s.i))
|
||||
if not s.slowSaid then s.slowSaid = true Say(FW.L.MAIL_SPEED_ADAPT) end
|
||||
pcall(ClearCursor)
|
||||
ClearAttachment()
|
||||
s.i = s.i - 1
|
||||
s.err, s.stage, s.nextAt = false, "next", now + Mail.gap + 0.5
|
||||
return
|
||||
elseif now > s.deadline then
|
||||
return self:FinishSend("timeout")
|
||||
end
|
||||
@@ -881,6 +940,7 @@ function Mail:OnMailShow()
|
||||
pcall(self.Purge, self)
|
||||
self.open = true
|
||||
self.gen = self.gen + 1
|
||||
self.boardTries, self.boardAutoAt, self.boardSending = 0, nil, nil
|
||||
self.selected = {}
|
||||
self:ApplyReplace()
|
||||
Trace("Briefkasten geoeffnet")
|
||||
@@ -904,6 +964,13 @@ function Mail:OnInboxUpdate()
|
||||
end
|
||||
|
||||
function Mail:OnSendSuccess()
|
||||
if self.boardSending then
|
||||
self.boardSending = nil
|
||||
local C = FW.Creator
|
||||
if C then C.mailChoice = nil end -- Brett-Brief ist raus: unser Fenster ist wieder frei
|
||||
Say(FW.L.MAIL_BOARD_SENT)
|
||||
FW:Fire("MAIL_STATE")
|
||||
end
|
||||
local s = self.send
|
||||
if self.lastTo then
|
||||
self:AddRecipient(self.lastTo)
|
||||
@@ -946,6 +1013,7 @@ function Mail:OnEnable()
|
||||
FW:RegisterEvent("MAIL_INBOX_UPDATE", function() pcall(Mail.OnInboxUpdate, Mail) end, self)
|
||||
FW:RegisterEvent("MAIL_SEND_SUCCESS", function() pcall(Mail.OnSendSuccess, Mail) end, self)
|
||||
FW:RegisterEvent("MAIL_FAILED", function() pcall(Mail.OnSendFailed, Mail) end, self)
|
||||
FW:On("CREATOR_MAIL_UPDATE", function() pcall(Mail.BoardAuto, Mail) end, self)
|
||||
if not self.hooked then
|
||||
self.hooked = true
|
||||
-- Empfaenger merken, egal wer sendet (auch das normale Fenster und Brett-Auftraege)
|
||||
@@ -974,6 +1042,7 @@ function Mail:OnDisable()
|
||||
for _, ev in ipairs({ "MAIL_SHOW", "MAIL_CLOSED", "MAIL_INBOX_UPDATE", "MAIL_SEND_SUCCESS", "MAIL_FAILED" }) do
|
||||
FW:UnregisterEvent(ev, self)
|
||||
end
|
||||
pcall(FW.Off, FW, "CREATOR_MAIL_UPDATE", self)
|
||||
if self.driver then self.driver:Hide() end
|
||||
self.run, self.send, self.busy = nil, nil, nil
|
||||
if self.hidden then
|
||||
|
||||
+62
-2
@@ -606,7 +606,7 @@ local function BuildSend(parent)
|
||||
dd:SetPoint("LEFT", toBox, "RIGHT", 8, 0)
|
||||
|
||||
Heading(f, T("MAIL_SUBJECT"), 0, -54)
|
||||
local subjBox = MakeEdit(f, 628, nil, 64)
|
||||
local subjBox = MakeEdit(f, 616, nil, 64) -- genauso breit wie das Textfeld (dessen Rollbalken nimmt 12 ab)
|
||||
subjBox:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -74)
|
||||
|
||||
Heading(f, T("MAIL_BODY"), 0, -108)
|
||||
@@ -642,6 +642,57 @@ local function BuildSend(parent)
|
||||
local send = UI.CreateButton(f, T("MAIL_SEND"), 150, 30, nil, "primary")
|
||||
send:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 0)
|
||||
|
||||
-- Brett-Brief: sichtbare Vorbereitung im eigenen Fenster (verdeckt das Formular, solange der Auftrag den Brief fuellt)
|
||||
local bl = UI.CreatePanel(f, "bgDeep", "gold")
|
||||
bl:SetPoint("TOPLEFT", f, "TOPLEFT", -8, 8)
|
||||
bl:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 8, -8)
|
||||
bl:SetFrameLevel(f:GetFrameLevel() + 30)
|
||||
bl:EnableMouse(true)
|
||||
bl:Hide()
|
||||
local blTitle = UI.CreateLabel(bl, T("MAIL_BOARD_TITLE"), { font = "heading", size = 15, color = "goldLight" })
|
||||
blTitle:SetPoint("TOPLEFT", bl, "TOPLEFT", 16, -14)
|
||||
bl.lines = {}
|
||||
for i = 1, 6 do
|
||||
local l = UI.CreateLabel(bl, "", { size = 12 })
|
||||
l:SetPoint("TOPLEFT", bl, "TOPLEFT", 16, -48 - (i - 1) * 24)
|
||||
l:SetPoint("TOPRIGHT", bl, "TOPRIGHT", -16, -48 - (i - 1) * 24)
|
||||
l:SetWordWrap(false)
|
||||
bl.lines[i] = l
|
||||
end
|
||||
bl.status = UI.CreateLabel(bl, "", { size = 12, color = "goldLight", justifyV = "TOP" })
|
||||
bl.status:SetPoint("TOPLEFT", bl, "TOPLEFT", 16, -208)
|
||||
bl.status:SetPoint("TOPRIGHT", bl, "TOPRIGHT", -16, -208)
|
||||
bl.status:SetHeight(48)
|
||||
bl.status:SetWordWrap(true)
|
||||
bl.add = UI.CreateButton(bl, T("MAIL_BOARD_ADD"), 180, 28, function()
|
||||
if FW.Creator and FW.Creator.MailAdd then pcall(FW.Creator.MailAdd) end
|
||||
if f.Refresh then f.Refresh() end
|
||||
end, "default")
|
||||
bl.add:SetPoint("BOTTOMLEFT", bl, "BOTTOMLEFT", 16, 16)
|
||||
bl.now = UI.CreateButton(bl, T("MAIL_BOARD_SEND"), 160, 28, function()
|
||||
Mail:BoardSend()
|
||||
if f.Refresh then f.Refresh() end
|
||||
end, "primary")
|
||||
bl.now:SetPoint("BOTTOMRIGHT", bl, "BOTTOMRIGHT", -16, 16)
|
||||
|
||||
local function BoardRefresh()
|
||||
local b = Mail.BoardLetter()
|
||||
if not b then bl:Hide() return false end
|
||||
bl:Show()
|
||||
for i, l in ipairs(bl.lines) do
|
||||
local c = b.list[i]
|
||||
l:SetText(c and ((c.ok and "|cff6cc070[x] " or "|cffff7060[ ] ") .. c.text .. "|r") or "")
|
||||
end
|
||||
local auto = Mail.db.settings.boardAuto
|
||||
if b.state == "locked" then bl.status:SetText("|cffff7060" .. T("MAIL_BOARD_LOCKED") .. "|r")
|
||||
elseif b.state == "armed" then bl.status:SetText(auto and T("MAIL_BOARD_READY_AUTO") or T("MAIL_BOARD_READY_MANUAL"))
|
||||
else bl.status:SetText(T("MAIL_BOARD_FILLING")) end
|
||||
bl.now:SetShown(b.state == "armed" and b.all)
|
||||
bl.add:SetShown(b.state == "filling" and not b.all)
|
||||
Mail:BoardAuto()
|
||||
return true
|
||||
end
|
||||
|
||||
local function Copper()
|
||||
return (tonumber(goldBox.edit:GetText()) or 0) * 10000 + (tonumber(silverBox.edit:GetText()) or 0) * 100 + (tonumber(copperBox.edit:GetText()) or 0)
|
||||
end
|
||||
@@ -662,6 +713,7 @@ local function BuildSend(parent)
|
||||
end
|
||||
|
||||
function f.Refresh()
|
||||
if BoardRefresh() then return end
|
||||
for i, pk in ipairs(picks) do local pk, i = pk, i
|
||||
local row = rows[i]
|
||||
if not row then
|
||||
@@ -1065,6 +1117,7 @@ local function HideWindow()
|
||||
end
|
||||
|
||||
FW:On("MAIL_WINDOW_SHOW", function() ShowWindow() end, OWNER)
|
||||
FW:On("CREATOR_MAIL_PREPARING", function() if window and window:IsShown() then SelectTab("send") end end, OWNER)
|
||||
FW:On("MAIL_WINDOW_HIDE", function() HideWindow() end, OWNER)
|
||||
FW:On("MAIL_STATE", function() RefreshCurrent() end, OWNER)
|
||||
FW:On("MAIL_INBOX_CHANGED", function() RefreshCurrent() end, OWNER)
|
||||
@@ -1078,7 +1131,7 @@ FW:On("MAIL_LISTS_CHANGED", function() RefreshCurrent() if picker and picker:IsS
|
||||
if UI.RegisterSettingsSection then
|
||||
UI:RegisterSettingsSection("mail", {
|
||||
order = 118,
|
||||
height = 190,
|
||||
height = 220,
|
||||
build = function(parent)
|
||||
local f, stack = UI.CreateSection(parent, T("MAIL_SET_HEADER"))
|
||||
local boxes = {}
|
||||
@@ -1096,6 +1149,13 @@ if UI.RegisterSettingsSection then
|
||||
end)
|
||||
stack:Add(chat, { fit = true, gap = 4 })
|
||||
boxes[#boxes + 1] = chat
|
||||
local boardAuto = UI.CreateCheckbox(f, T("MAIL_SET_BOARDAUTO"), function()
|
||||
return Mail.db.settings.boardAuto
|
||||
end, function(value)
|
||||
Mail.db.settings.boardAuto = value and true or false
|
||||
end)
|
||||
stack:Add(boardAuto, { fit = true, gap = 4 })
|
||||
boxes[#boxes + 1] = boardAuto
|
||||
local cleanup = UI.CreateCheckbox(f, T("MAIL_SET_CLEANUP"), function()
|
||||
return Mail.db.settings.cleanup
|
||||
end, function(value)
|
||||
|
||||
Reference in New Issue
Block a user