changeset 18:a3328fffef5c

Split of main file into components
author wobin
date Thu, 07 May 2009 02:52:23 +1000
parents 2a73deb7bc54
children 431f2fce08f2
files Controller.lua Model.lua Squawk.lua Squawk.toc View.lua
diffstat 5 files changed, 603 insertions(+), 538 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Controller.lua	Thu May 07 02:52:23 2009 +1000
@@ -0,0 +1,127 @@
+local Controller = Squawk.Controller
+local Model = Squawk.Model
+local View = Squawk.View
+local Settings = Model.UserSettings
+local Squawks = Model.Squawks
+
+--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, Squawks: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
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Model.lua	Thu May 07 02:52:23 2009 +1000
@@ -0,0 +1,222 @@
+local Model = Squawk.Model
+local Settings = Model.UserSettings
+local Controller = Squawk.Controller
+local View = Squawk.View
+
+
+-- 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
+	
+	if #o.Related == 0 then
+		o.Related = nil
+	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:Reload()
+	for _,squawk in ipairs(Model.Squawks.Main) do
+		if not self.Owners[squawk.Owner] then
+			self.Owners[squawk.Owner] = {}
+		end
+		table.insert(self.Owners[squawk.Owner], squawk)
+		if squawk.Related and #squawk.Related == 0 then
+			squawk.Related = nil
+		end
+	end
+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 = self: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
--- a/Squawk.lua	Sun May 03 00:00:24 2009 +1000
+++ b/Squawk.lua	Thu May 07 02:52:23 2009 +1000
@@ -1,566 +1,47 @@
--- 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 = {},
+	}
+}
+local SquawkViewMeta = { __tostring = function() return "SquawkView" end }
+
+function Squawk:OnInitialize()
+	Model.db = LibStub("AceDB-3.0"):New("SquawkDB", defaults)
+	Model.Squawks.Main = 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)
+	setmetatable(View, SquawkViewMeta)
+
+	Model.Squawks.Reload(Model.Squawks) -- Retrain the table lookups
+end
--- a/Squawk.toc	Sun May 03 00:00:24 2009 +1000
+++ b/Squawk.toc	Thu May 07 02:52:23 2009 +1000
@@ -13,4 +13,7 @@
 Locale\Localization.enUS.lua
 
 Squawk.lua
+Model.lua
+Controller.lua
+View.lua
 Tests.lua
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/View.lua	Thu May 07 02:52:23 2009 +1000
@@ -0,0 +1,204 @@
+local View = Squawk.View
+local Model = Squawk.Model
+local Settings = Model.UserSettings
+local Controller = Squawk.Controller
+local Squawks = Model.Squawks
+
+-- 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(Squawks:GetLast10()) 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
+--]]
+