Mercurial > wow > squawk
changeset 17:2a73deb7bc54
For Mikma.
author | wobin |
---|---|
date | Sun, 03 May 2009 00:00:24 +1000 |
parents | 6c28e55a00cf |
children | a3328fffef5c |
files | Squawk.lua reply.tga |
diffstat | 2 files changed, 566 insertions(+), 538 deletions(-) [+] |
line wrap: on
line diff
--- a/Squawk.lua Sat May 02 23:54:32 2009 +1000 +++ b/Squawk.lua Sun May 03 00:00:24 2009 +1000 @@ -1,566 +1,566 @@ --- A Twitter client of sorts for World of Warcraft --- Author: Wobin --- Email: wobster@gmail.com --- -Squawk = LibStub("AceAddon-3.0"):NewAddon("Squawk") - -Squawk.Model = {} -Squawk.View = {} -Squawk.Controller = {} - -local Model = Squawk.Model -local View = Squawk.View -local Controller = Squawk.Controller - -Model.UserSettings = {} -local Settings = Model.UserSettings - -local defaults = { - profile = { - Squawks = {}, - Follower = {}, - Following = {}, - Pending = {}, - Requested = {}, - Blocked = {}, - } -} - -function Squawk:OnInitialize() - Model.db = LibStub("AceDB-3.0"):New("SquawkDB", defaults) - Model.Squawks = Model.db.profile.Squawks - Settings.Follower = Model.db.profile.Follower - Settings.Following = Model.db.profile.Following - Settings.Pending = Model.db.profile.Pending - Settings.Requested = Model.db.profile.Requested - Settings.Blocked = Model.db.profile.Blocked - Settings.Private = Model.db.profile.Private - - LibStub("AceComm-3.0"):Embed(Controller) - LibStub("AceTimer-3.0"):Embed(Controller) - Controller:RegisterComm("Squawk", Controller.ReceiveMessage) - LibStub("AceConsole-3.0"):Embed(View) - -end - --- Model -- ---[[ ---Each Squawk will have the following information: --- * Owner (Name) --- * Time (Epoch) --- * Message (140 characters) --- * ReplyTo (Name) --- * Related (Names) --- --- Each User will have the following lists: --- * Follower --- * Following --- * Blocked --- * Pending (Requests to follow that you haven't acted on) --- * Requested (Requests to follow that you have made) --- * Privacy State --- --- A user can only request to follow an online person. Requests can be approved --- on or offline, but the initial request must be made online. --- --- When a user makes a request to follow a private user, the subsequent paths occur: --- - Followee is added to Settings.Requested --- - Followee receives 'follow request' -> (their) Settings.Pending --- - Followee acts on request -> (their) Settings.Pending cleared --- 1) Follwer is online --- - Follower receives 'request accepted' -> Added to Settings.Following and --- cleared from Settings.Requested --- 2) Follower is offline --- - The next time Follower is online and recieves a Squawk we check if there --- is a Settings.Requested for that name, and if so assume they have approved --- and clear/add records appropriately. --- --- For updating, there can be a few methods. --- --- Guild open: you're not private, you broadcast to the guild your last X --- squawks on login --- --- followers: ---]] -Model.Squawks = {} -local Squawks = Model.Squawks -Squawks.Main = {} -Squawks.Owners = {} - -local function wrap(str, limit) - limit = limit or 72 - local here = 1 - return str:gsub("(%s+)()(%S+)()", - function(sp, st, word, fi) - if fi-here > limit then - here = st - return "\n"..word - end - end) -end - -function Squawks:new(Message, Owner) - local o = {} - o.Owner = Owner or UnitName("player") - o.Message = wrap(Message) - o.Time = time() - local reply, to = strsplit("@", ((strsplit(" ", Message)))) - if reply == "" then - o.ReplyTo = to - end - - o.Related = {} - - for word in string.gmatch(Message, "@(%a+)") do - if word ~= o.ReplyTo or "" then - table.insert(o.Related, word) - end - end - - table.insert(self.Main, o) - - if not self.Owners[Owner] then - self.Owners[Owner] = {} - end - table.insert(self.Owners[Owner], o) - - return o -end - -function Squawks:Sort(Squawks) - table.sort(Squawks or self.Main, function(a,b) return a.Time > b.Time end) - return Squawks or self.Main -end - -function Squawks:GetOwn(Squawks) - local mine = {} - for _, squawk in ipairs(Squawks or self.Main) do - if squawk.Owner == UnitName("player") then - table.insert(mine, squawk) - end - end - return self:Sort(mine) -end - -function Squawks:GetLast10(Squawks) - local mine = {} - Squawks = Squawks or self.Main - local limit = #Squawks < 10 and #Squawks or 10 - - Squawks = Squawk:Sort(Squawks) - - for i=1,limit do - table.insert(mine, Squawks[i]) - end - return mine -end - --- initially called with no arguments to get the latest timestamp of --- my squawks, or with a name to find the latest timestamp of all --- squawks from that user -function Squawks:GetLatestTimestamp(Name, Squawks) - if Name then - if self.Owners[Name] then - return self:GetLatestTimestamp(nil, self.Owners[Name]) - else - return -1 -- No squawks exist for that name in our records - end - end - - Squawks = Squawks or self.Main or {} - local latest = self:Sort(Squawks) - return latest and #latest > 0 and latest[1].Time or -1 -end - -function Squawks:GetLatestSquawks(Timestamp) - local latest = {} - for i, squawk in ipairs(self:Sort()) do - if squawk.Time > Timestamp and i < 10 then - table.insert(latest, squawk) - else - return latest - end - end -end - -function Settings:IsPrivate() - return Settings.Private -end - -function Settings:TogglePrivate() - Settings.Private = not Settings.Private -end - -function Settings:AddFollower(Name) - Settings.Follower[Name] = 1 - self:RemovePending(Name) -end - -function Settings:AddFollowing(Name) - Settings.Following[Name] = 1 - self:RemoveRequested(Name) -end - -function Settings:AddBlock(Name) - Settings.Blocked[Name] = 1 - self:RemoveFollower(Name) - self:RemoveFollowing(Name) -end - -function Settings:AddPending(Name) - Settings.Pending[Name] = 1 -end - -function Settings:AddRequested(Name) - Settings.Requested[Name] = 1 -end - -function Settings:RemoveFollower(Name) - if Settings.Follower[Name] then - Settings.Follower[Name] = nil - end -end - -function Settings:RemoveFollowing(Name) - if Settings.Following[Name] then - Settings.Following[Name] = nil - end -end - -function Settings:RemoveBlock(Name) - if Settings.Blocked[Name] then - Settings.Blocked[Name] = nil - end -end - -function Settings:RemovePending(Name) - if Settings.Pending[Name] then - Settings.Pending[Name] = nil - end -end - -function Settings:RemoveRequested(Name) - if Settings.Requested[Name] then - Settings.Requested[Name] = nil - end -end - ---Controller-- - -function Controller:TheyWantToFollowMe(Name) - if Settings:IsPrivate() then - Settings:AddPending(Name) - self:PutForwardFollowRequest(Name) - self:SendMessageToTarget(Name, "#Pending|"..UnitName("player")) - else - Settings:AddFollower(Name) - View:NotifyOfNewFollower(Name) - self:SendMessageToTarget(Name, "#Follow|"..UnitName("player")) - end -end - -function Controller:TheyWantToUnfollowMe(Name) - Settings:RemoveFollower(Name) -end - -function Controller:IWantToFollowThem(Name) - self:SendMessageToTarget(Name, "#Request|"..UnitName("player")) - Settings:AddRequested(Name) -end - -function Controller:IWantToUnfollowThem(Name) - Settings:RemoveFollowing(Name) - self:SendMessageToTarget(Name, "#Unfollow|"..UnitName("player")) - View:NotifyOfUnfollowing(Name) -end - -function Controller:IAmNowFollowingThem(Name) - Settings:AddFollowing(Name) - View:NotifyOfNewFollowing(Name) -end - -function Controller:AddANewSquawk(Name, Message, Source) - if not Settings.Blocked[Name] then - - if Source == "WHISPER" then - if Settings.Requested[Name] then -- We've been approved offline! - Settings:AddFollowing(Name) - end - - if not Settings.Following[Name] then -- If we're no longer following this person - self:SendMessageToTarget(Name, "#Unfollow|"..UnitName("player")) - return - end - end - - if Source == "GUILD" and Name == UnitName("player") then - return - end - - table.insert(Model.Squawks, Squawk:new(Message, Name)) - View:UpdateSquawkList() - end -end - -local trigger -local function RepressFailure(frame, event, ...) - if arg1:match(string.gsub(ERR_CHAT_PLAYER_NOT_FOUND_S, "%%s", "(.*)")) then - if trigger then Controller:CancelTimer(trigger, true) end - trigger = Controller:ScheduleTimer( - function() - ChatFrame_RemoveMessageEventFilter("CHAT_MSG_SYSTEM", RepressFailure) - end, 3) -- Give it three seconds and then remove the filter. - return true - else - return false, unpack(...) - end -end - -function Controller:SendNewSquawk(Message) - if not Settings:IsPrivate() then - self:SendMessageToGuild("#Squawk|"..UnitName("player").."|"..Message) - end - - self:AddANewSquawk(UnitName("player"), Message) - for name, _ in pairs(Settings.Following) do - self:SendMessageToTarget(name, "#Squawk|"..UnitName("player").."|"..Message) - end -end - -function Controller:ImPending(Name) - View:NotifyOfPending(Name) -end - -function Controller:PutForwardFollowRequest(Name) - View:NotifyOfPendingRequest(Name) -end - -function Controller:ApprovePendingRequest(Name) - Settings:AddFollower(Name) - View:NotifyOfNewFollower(Name) - self:SendMessageToTarget(Name, "#Follow|"..UnitName("player")) -end - - - -function Controller:SendMessageToTarget(Name, Message) - ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", RepressFailure) - self:SendCommMessage("Squawk", Message, "WHISPER", Name) -end - -function Controller:SendMessageToGuild(Message) - self:SendCommMessage("Squawk", Message, "GUILD") -end - -local Parse = { - ["#Pending"] = Controller.ImPending, - ["#Follow"] = Controller.IAmNowFollowingThem, - ["#Unfollow"] = Controller.TheyWantToUnfollowMe, - ["#Squawk"] = Controller.AddANewSquawk, - ["#Request"] = Controller.TheyWantToFollowMe, - } - -function Controller:ReceiveMessage(Message, Distribution, Sender) - local command, name, info = strsplit("|",Message) - View:Print(Distribution..":"..Message) - Parse[command](Controller, name, info, Distribution) -end - --- View -- - -function View:UpdateSquawkList() - self:Print("Updated Squawk List") - self:ShowMeMySquawks() -end - -function View:NotifyOfPending(Name) - self:Print(Name.." will have to approve your request") -end - -function View:NotifyOfPendingRequest(Name) - self:Print(Name.." wants to follow you.") -end - -function View:NotifyOfNewFollowing(Name) - self:Print("You are now following "..Name) -end - -function View:NotifyOfUnfollowing(Name) - self:Print("You are no longer following "..Name) -end - -function View:NotifyOfNewFollower(Name) - self:Print(Name.." is now following you") -end - -function View:ShowMeMySquawks() - for _,squawk in ipairs(Model.Squawks.Main) do - self:Print(squawk.Message) - end -end - -function View:ShowMeMyFollowers() - self:Print("My followers are:") - for name,_ in pairs(Settings.Follower) do - self:Print(name) - end -end - -function View:ShowMeWhoImFollowing() - self:Print("I am following:") - for name,_ in pairs(Settings.Following) do - self:Print(name) - end -end - -function View:ShowMeWhoIveBlocked() - self:Print("I've blocked:") - for name,_ in pairs(Settings.Blocked) do - self:Print(name) - end -end - -local TimeSpan = { [1] = {"second", 60, 1}, - [2] = {"minute", 3600, 60}, - [3] = {"hour", 86400, 3600} } - -function View:GetTime(stime) - local lapsed = difftime(time(), stime) - if lapsed < 86400 then -- if we're still in the same day... - for _,span in ipairs(TimeSpan) do - if lapsed < span[2] then - local timespan = math.floor(lapsed/span[3]) - if timespan == 1 then - timespan = timespan .." ".. span[1] - else - timespan = timespan .. " ".. span[1].."s" - end - return timespan.. " ago" - end - end - end - return date("%I:%M %p %b %d", stime) -end - -local LDBFeed = LibStub("LibDataBroker-1.1"):NewDataObject("Squawk", {type = "data source", text = "Awk!"}) -local QTip = LibStub("LibQTip-1.0") -local QTipClick = LibStub("LibQTipClick-1.0") -local tooltip = {} - -local function HideTooltip() - if MouseIsOver(tooltip) then return end - tooltip:SetScript("OnLeave", nil) - tooltip:Hide() - QTip:Release(tooltip) - tooltip = nil -end - -local function ReplyToMe(cell, Owner, event) - View:Print("Replying to @"..Owner) -end - -local function AddLine(tooltip, Line, Number, Owner, TimeStamp) - local x,y - if #Line < 79 then - y,x = tooltip:AddNormalLine(Number, Owner, Line, TimeStamp) - else - y,x = tooltip:AddNormalLine(Number, Owner, Line:sub(1, 80).."-", TimeStamp) - AddLine(tooltip, Line:sub(81)) - end - if not TimeStamp then return end - - -- Now add the reply clickback - tooltip:SetCell(y, 5, " ", Owner) - tooltip.lines[y].cells[5]:SetBackdrop({bgFile= "Interface\\Addons\\Squawk\\reply"}) - if not tooltip.lines[y].cells[5]:GetScript("OnHide") then - tooltip.lines[y].cells[5]:SetScript("OnHide", function(self) self:SetBackdrop(nil) self:SetScript("OnHide", nil) end) - end - -- Reply clickback finished -end - -function LDBFeed:OnEnter() - tooltip = QTipClick:Acquire("Squawk",5, "LEFT", "CENTER", "LEFT", "RIGHT", "RIGHT") - tooltip:Clear() - tooltip:SetCallback("OnMouseDown", ReplyToMe) - self.tooltip = tooltip - for i,squawk in ipairs(Squawk:GetLast10(Model.Squawks)) do - local head = true - local message = {strsplit("\n",squawk.Message)} - for _,line in ipairs(message) do - if head then - AddLine(tooltip, line, i..".", squawk.Owner, View:GetTime(squawk.Time)) - head = false - else - AddLine(tooltip, line) - end - end - end - tooltip:SmartAnchorTo(self) - tooltip:SetScript("OnLeave", HideTooltip) - tooltip:Show() -end - -function LDBFeed:OnLeave() - HideTooltip() -end ---[[ - -function LDBFeed:OnClick(button) - editbox:ClearAllPoints() - editbox:SetPoint(GetTipAnchor(self)) - editbox:Show() -end - -local function GetTipAnchor(frame) - if not x or not y then return "TOPLEFT", frame, "BOTTOMLEFT" end - local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or "" - local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM" - return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf -end - -local editbox = CreateFrame('EditBox', nil, UIParent) -editbox:Hide() -editbox:SetAutoFocus(true) -editbox:SetHeight(32) -editbox:SetWidth(350) -editbox:SetFrameStrata("HIGH") -editbox:SetFontObject('GameFontHighlightSmall') -lib.editbox = editbox - -editbox:SetScript("OnEscapePressed", editbox.ClearFocus) -editbox:SetScript("OnEnterPressed", editbox.ClearFocus) -editbox:SetScript("OnEditFocusLost", editbox.Hide) -editbox:SetScript("OnEditFocusGained", editbox.HighlightText) -editbox:SetScript("OnTextChanged", function(self) - self:SetText(self:GetParent().val) - self:HighlightText() -end) - - local left = editbox:CreateTexture(nil, "BACKGROUND") - left:SetWidth(8) left:SetHeight(20) - left:SetPoint("LEFT", -5, 0) - left:SetTexture("Interface\\Common\\Common-Input-Border") - left:SetTexCoord(0, 0.0625, 0, 0.625) - - local right = editbox:CreateTexture(nil, "BACKGROUND") - right:SetWidth(8) right:SetHeight(20) - right:SetPoint("RIGHT", 0, 0) - right:SetTexture("Interface\\Common\\Common-Input-Border") - right:SetTexCoord(0.9375, 1, 0, 0.625) - - local center = editbox:CreateTexture(nil, "BACKGROUND") - center:SetHeight(20) - center:SetPoint("RIGHT", right, "LEFT", 0, 0) - center:SetPoint("LEFT", left, "RIGHT", 0, 0) - center:SetTexture("Interface\\Common\\Common-Input-Border") - center:SetTexCoord(0.0625, 0.9375, 0, 0.625) - -function lib.OpenEditbox(self) - editbox:SetText(self.val) - editbox:SetParent(self) - editbox:SetPoint("LEFT", self) - editbox:SetPoint("RIGHT", self) - editbox:Show() -end ---]] - +-- A Twitter client of sorts for World of Warcraft +-- Author: Wobin +-- Email: wobster@gmail.com +-- +Squawk = LibStub("AceAddon-3.0"):NewAddon("Squawk") + +Squawk.Model = {} +Squawk.View = {} +Squawk.Controller = {} + +local Model = Squawk.Model +local View = Squawk.View +local Controller = Squawk.Controller + +Model.UserSettings = {} +local Settings = Model.UserSettings + +local defaults = { + profile = { + Squawks = {}, + Follower = {}, + Following = {}, + Pending = {}, + Requested = {}, + Blocked = {}, + } +} + +function Squawk:OnInitialize() + Model.db = LibStub("AceDB-3.0"):New("SquawkDB", defaults) + Model.Squawks = Model.db.profile.Squawks + Settings.Follower = Model.db.profile.Follower + Settings.Following = Model.db.profile.Following + Settings.Pending = Model.db.profile.Pending + Settings.Requested = Model.db.profile.Requested + Settings.Blocked = Model.db.profile.Blocked + Settings.Private = Model.db.profile.Private + + LibStub("AceComm-3.0"):Embed(Controller) + LibStub("AceTimer-3.0"):Embed(Controller) + Controller:RegisterComm("Squawk", Controller.ReceiveMessage) + LibStub("AceConsole-3.0"):Embed(View) + +end + +-- Model -- +--[[ +--Each Squawk will have the following information: +-- * Owner (Name) +-- * Time (Epoch) +-- * Message (140 characters) +-- * ReplyTo (Name) +-- * Related (Names) +-- +-- Each User will have the following lists: +-- * Follower +-- * Following +-- * Blocked +-- * Pending (Requests to follow that you haven't acted on) +-- * Requested (Requests to follow that you have made) +-- * Privacy State +-- +-- A user can only request to follow an online person. Requests can be approved +-- on or offline, but the initial request must be made online. +-- +-- When a user makes a request to follow a private user, the subsequent paths occur: +-- - Followee is added to Settings.Requested +-- - Followee receives 'follow request' -> (their) Settings.Pending +-- - Followee acts on request -> (their) Settings.Pending cleared +-- 1) Follwer is online +-- - Follower receives 'request accepted' -> Added to Settings.Following and +-- cleared from Settings.Requested +-- 2) Follower is offline +-- - The next time Follower is online and recieves a Squawk we check if there +-- is a Settings.Requested for that name, and if so assume they have approved +-- and clear/add records appropriately. +-- +-- For updating, there can be a few methods. +-- +-- Guild open: you're not private, you broadcast to the guild your last X +-- squawks on login +-- +-- followers: +--]] +Model.Squawks = {} +local Squawks = Model.Squawks +Squawks.Main = {} +Squawks.Owners = {} + +local function wrap(str, limit) + limit = limit or 72 + local here = 1 + return str:gsub("(%s+)()(%S+)()", + function(sp, st, word, fi) + if fi-here > limit then + here = st + return "\n"..word + end + end) +end + +function Squawks:new(Message, Owner) + local o = {} + o.Owner = Owner or UnitName("player") + o.Message = wrap(Message) + o.Time = time() + local reply, to = strsplit("@", ((strsplit(" ", Message)))) + if reply == "" then + o.ReplyTo = to + end + + o.Related = {} + + for word in string.gmatch(Message, "@(%a+)") do + if word ~= o.ReplyTo or "" then + table.insert(o.Related, word) + end + end + + table.insert(self.Main, o) + + if not self.Owners[Owner] then + self.Owners[Owner] = {} + end + table.insert(self.Owners[Owner], o) + + return o +end + +function Squawks:Sort(Squawks) + table.sort(Squawks or self.Main, function(a,b) return a.Time > b.Time end) + return Squawks or self.Main +end + +function Squawks:GetOwn(Squawks) + local mine = {} + for _, squawk in ipairs(Squawks or self.Main) do + if squawk.Owner == UnitName("player") then + table.insert(mine, squawk) + end + end + return self:Sort(mine) +end + +function Squawks:GetLast10(Squawks) + local mine = {} + Squawks = Squawks or self.Main + local limit = #Squawks < 10 and #Squawks or 10 + + Squawks = Squawk:Sort(Squawks) + + for i=1,limit do + table.insert(mine, Squawks[i]) + end + return mine +end + +-- initially called with no arguments to get the latest timestamp of +-- my squawks, or with a name to find the latest timestamp of all +-- squawks from that user +function Squawks:GetLatestTimestamp(Name, Squawks) + if Name then + if self.Owners[Name] then + return self:GetLatestTimestamp(nil, self.Owners[Name]) + else + return -1 -- No squawks exist for that name in our records + end + end + + Squawks = Squawks or self.Main or {} + local latest = self:Sort(Squawks) + return latest and #latest > 0 and latest[1].Time or -1 +end + +function Squawks:GetLatestSquawks(Timestamp) + local latest = {} + for i, squawk in ipairs(self:Sort()) do + if squawk.Time > Timestamp and i < 10 then + table.insert(latest, squawk) + else + return latest + end + end +end + +function Settings:IsPrivate() + return Settings.Private +end + +function Settings:TogglePrivate() + Settings.Private = not Settings.Private +end + +function Settings:AddFollower(Name) + Settings.Follower[Name] = 1 + self:RemovePending(Name) +end + +function Settings:AddFollowing(Name) + Settings.Following[Name] = 1 + self:RemoveRequested(Name) +end + +function Settings:AddBlock(Name) + Settings.Blocked[Name] = 1 + self:RemoveFollower(Name) + self:RemoveFollowing(Name) +end + +function Settings:AddPending(Name) + Settings.Pending[Name] = 1 +end + +function Settings:AddRequested(Name) + Settings.Requested[Name] = 1 +end + +function Settings:RemoveFollower(Name) + if Settings.Follower[Name] then + Settings.Follower[Name] = nil + end +end + +function Settings:RemoveFollowing(Name) + if Settings.Following[Name] then + Settings.Following[Name] = nil + end +end + +function Settings:RemoveBlock(Name) + if Settings.Blocked[Name] then + Settings.Blocked[Name] = nil + end +end + +function Settings:RemovePending(Name) + if Settings.Pending[Name] then + Settings.Pending[Name] = nil + end +end + +function Settings:RemoveRequested(Name) + if Settings.Requested[Name] then + Settings.Requested[Name] = nil + end +end + +--Controller-- + +function Controller:TheyWantToFollowMe(Name) + if Settings:IsPrivate() then + Settings:AddPending(Name) + self:PutForwardFollowRequest(Name) + self:SendMessageToTarget(Name, "#Pending|"..UnitName("player")) + else + Settings:AddFollower(Name) + View:NotifyOfNewFollower(Name) + self:SendMessageToTarget(Name, "#Follow|"..UnitName("player")) + end +end + +function Controller:TheyWantToUnfollowMe(Name) + Settings:RemoveFollower(Name) +end + +function Controller:IWantToFollowThem(Name) + self:SendMessageToTarget(Name, "#Request|"..UnitName("player")) + Settings:AddRequested(Name) +end + +function Controller:IWantToUnfollowThem(Name) + Settings:RemoveFollowing(Name) + self:SendMessageToTarget(Name, "#Unfollow|"..UnitName("player")) + View:NotifyOfUnfollowing(Name) +end + +function Controller:IAmNowFollowingThem(Name) + Settings:AddFollowing(Name) + View:NotifyOfNewFollowing(Name) +end + +function Controller:AddANewSquawk(Name, Message, Source) + if not Settings.Blocked[Name] then + + if Source == "WHISPER" then + if Settings.Requested[Name] then -- We've been approved offline! + Settings:AddFollowing(Name) + end + + if not Settings.Following[Name] then -- If we're no longer following this person + self:SendMessageToTarget(Name, "#Unfollow|"..UnitName("player")) + return + end + end + + if Source == "GUILD" and Name == UnitName("player") then + return + end + + table.insert(Model.Squawks, Squawk:new(Message, Name)) + View:UpdateSquawkList() + end +end + +local trigger +local function RepressFailure(frame, event, ...) + if arg1:match(string.gsub(ERR_CHAT_PLAYER_NOT_FOUND_S, "%%s", "(.*)")) then + if trigger then Controller:CancelTimer(trigger, true) end + trigger = Controller:ScheduleTimer( + function() + ChatFrame_RemoveMessageEventFilter("CHAT_MSG_SYSTEM", RepressFailure) + end, 3) -- Give it three seconds and then remove the filter. + return true + else + return false, unpack(...) + end +end + +function Controller:SendNewSquawk(Message) + if not Settings:IsPrivate() then + self:SendMessageToGuild("#Squawk|"..UnitName("player").."|"..Message) + end + + self:AddANewSquawk(UnitName("player"), Message) + for name, _ in pairs(Settings.Following) do + self:SendMessageToTarget(name, "#Squawk|"..UnitName("player").."|"..Message) + end +end + +function Controller:ImPending(Name) + View:NotifyOfPending(Name) +end + +function Controller:PutForwardFollowRequest(Name) + View:NotifyOfPendingRequest(Name) +end + +function Controller:ApprovePendingRequest(Name) + Settings:AddFollower(Name) + View:NotifyOfNewFollower(Name) + self:SendMessageToTarget(Name, "#Follow|"..UnitName("player")) +end + + + +function Controller:SendMessageToTarget(Name, Message) + ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", RepressFailure) + self:SendCommMessage("Squawk", Message, "WHISPER", Name) +end + +function Controller:SendMessageToGuild(Message) + self:SendCommMessage("Squawk", Message, "GUILD") +end + +local Parse = { + ["#Pending"] = Controller.ImPending, + ["#Follow"] = Controller.IAmNowFollowingThem, + ["#Unfollow"] = Controller.TheyWantToUnfollowMe, + ["#Squawk"] = Controller.AddANewSquawk, + ["#Request"] = Controller.TheyWantToFollowMe, + } + +function Controller:ReceiveMessage(Message, Distribution, Sender) + local command, name, info = strsplit("|",Message) + View:Print(Distribution..":"..Message) + Parse[command](Controller, name, info, Distribution) +end + +-- View -- + +function View:UpdateSquawkList() + self:Print("Updated Squawk List") + self:ShowMeMySquawks() +end + +function View:NotifyOfPending(Name) + self:Print(Name.." will have to approve your request") +end + +function View:NotifyOfPendingRequest(Name) + self:Print(Name.." wants to follow you.") +end + +function View:NotifyOfNewFollowing(Name) + self:Print("You are now following "..Name) +end + +function View:NotifyOfUnfollowing(Name) + self:Print("You are no longer following "..Name) +end + +function View:NotifyOfNewFollower(Name) + self:Print(Name.." is now following you") +end + +function View:ShowMeMySquawks() + for _,squawk in ipairs(Model.Squawks.Main) do + self:Print(squawk.Message) + end +end + +function View:ShowMeMyFollowers() + self:Print("My followers are:") + for name,_ in pairs(Settings.Follower) do + self:Print(name) + end +end + +function View:ShowMeWhoImFollowing() + self:Print("I am following:") + for name,_ in pairs(Settings.Following) do + self:Print(name) + end +end + +function View:ShowMeWhoIveBlocked() + self:Print("I've blocked:") + for name,_ in pairs(Settings.Blocked) do + self:Print(name) + end +end + +local TimeSpan = { [1] = {"second", 60, 1}, + [2] = {"minute", 3600, 60}, + [3] = {"hour", 86400, 3600} } + +function View:GetTime(stime) + local lapsed = difftime(time(), stime) + if lapsed < 86400 then -- if we're still in the same day... + for _,span in ipairs(TimeSpan) do + if lapsed < span[2] then + local timespan = math.floor(lapsed/span[3]) + if timespan == 1 then + timespan = timespan .." ".. span[1] + else + timespan = timespan .. " ".. span[1].."s" + end + return timespan.. " ago" + end + end + end + return date("%I:%M %p %b %d", stime) +end + +local LDBFeed = LibStub("LibDataBroker-1.1"):NewDataObject("Squawk", {type = "data source", text = "Awk!"}) +local QTip = LibStub("LibQTip-1.0") +local QTipClick = LibStub("LibQTipClick-1.0") +local tooltip = {} + +local function HideTooltip() + if MouseIsOver(tooltip) then return end + tooltip:SetScript("OnLeave", nil) + tooltip:Hide() + QTip:Release(tooltip) + tooltip = nil +end + +local function ReplyToMe(cell, Owner, event) + View:Print("Replying to @"..Owner) +end + +local function AddLine(tooltip, Line, Number, Owner, TimeStamp) + local x,y + if #Line < 79 then + y,x = tooltip:AddNormalLine(Number, Owner, Line, TimeStamp) + else + y,x = tooltip:AddNormalLine(Number, Owner, Line:sub(1, 80).."-", TimeStamp) + AddLine(tooltip, Line:sub(81)) + end + if not TimeStamp then return end + + -- Now add the reply clickback + tooltip:SetCell(y, 5, " ", Owner) + tooltip.lines[y].cells[5]:SetBackdrop({bgFile= "Interface\\Addons\\Squawk\\reply"}) + if not tooltip.lines[y].cells[5]:GetScript("OnHide") then + tooltip.lines[y].cells[5]:SetScript("OnHide", function(self) self:SetBackdrop(nil) self:SetScript("OnHide", nil) end) + end + -- Reply clickback finished +end + +function LDBFeed:OnEnter() + tooltip = QTipClick:Acquire("Squawk",5, "LEFT", "CENTER", "LEFT", "RIGHT", "RIGHT") + tooltip:Clear() + tooltip:SetCallback("OnMouseDown", ReplyToMe) + self.tooltip = tooltip + for i,squawk in ipairs(Squawk:GetLast10(Model.Squawks)) do + local head = true + local message = {strsplit("\n",squawk.Message)} + for _,line in ipairs(message) do + if head then + AddLine(tooltip, line, i..".", squawk.Owner, View:GetTime(squawk.Time)) + head = false + else + AddLine(tooltip, line) + end + end + end + tooltip:SmartAnchorTo(self) + tooltip:SetScript("OnLeave", HideTooltip) + tooltip:Show() +end + +function LDBFeed:OnLeave() + HideTooltip() +end +--[[ + +function LDBFeed:OnClick(button) + editbox:ClearAllPoints() + editbox:SetPoint(GetTipAnchor(self)) + editbox:Show() +end + +local function GetTipAnchor(frame) + if not x or not y then return "TOPLEFT", frame, "BOTTOMLEFT" end + local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or "" + local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM" + return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf +end + +local editbox = CreateFrame('EditBox', nil, UIParent) +editbox:Hide() +editbox:SetAutoFocus(true) +editbox:SetHeight(32) +editbox:SetWidth(350) +editbox:SetFrameStrata("HIGH") +editbox:SetFontObject('GameFontHighlightSmall') +lib.editbox = editbox + +editbox:SetScript("OnEscapePressed", editbox.ClearFocus) +editbox:SetScript("OnEnterPressed", editbox.ClearFocus) +editbox:SetScript("OnEditFocusLost", editbox.Hide) +editbox:SetScript("OnEditFocusGained", editbox.HighlightText) +editbox:SetScript("OnTextChanged", function(self) + self:SetText(self:GetParent().val) + self:HighlightText() +end) + + local left = editbox:CreateTexture(nil, "BACKGROUND") + left:SetWidth(8) left:SetHeight(20) + left:SetPoint("LEFT", -5, 0) + left:SetTexture("Interface\\Common\\Common-Input-Border") + left:SetTexCoord(0, 0.0625, 0, 0.625) + + local right = editbox:CreateTexture(nil, "BACKGROUND") + right:SetWidth(8) right:SetHeight(20) + right:SetPoint("RIGHT", 0, 0) + right:SetTexture("Interface\\Common\\Common-Input-Border") + right:SetTexCoord(0.9375, 1, 0, 0.625) + + local center = editbox:CreateTexture(nil, "BACKGROUND") + center:SetHeight(20) + center:SetPoint("RIGHT", right, "LEFT", 0, 0) + center:SetPoint("LEFT", left, "RIGHT", 0, 0) + center:SetTexture("Interface\\Common\\Common-Input-Border") + center:SetTexCoord(0.0625, 0.9375, 0, 0.625) + +function lib.OpenEditbox(self) + editbox:SetText(self.val) + editbox:SetParent(self) + editbox:SetPoint("LEFT", self) + editbox:SetPoint("RIGHT", self) + editbox:Show() +end +--]] +