local V={}V.__index=V function V.CreateGuiObjects(y,V)local A=Instance.new("\070\114\097\109\101")A.Selectable=false A.Size=UDim2.new(1,0,1,0)A.BackgroundTransparency=1 A.Parent=V local j=Instance.new("\070\114\097\109\101")j.Selectable=false j.Name="\083\099\114\111\108\108\105\110\103\066\097\115\101"j.BackgroundTransparency=1 j.ClipsDescendants=true j.Size=UDim2.new(1,0,1,0)j.Position=UDim2.new(0,0,0,0)j.Parent=A local a=Instance.new("\070\114\097\109\101")a.Selectable=false a.Name="\083\099\114\111\108\108\101\114\083\105\122\101\114"a.BackgroundTransparency=1 a.Size=UDim2.new(1,0,1,0)a.Position=UDim2.new(0,0,0,0)a.Parent=j local E=Instance.new("\070\114\097\109\101")E.Selectable=false E.Name="\083\099\114\111\108\108\101\114\070\114\097\109\101"E.BackgroundTransparency=1 E.Size=UDim2.new(1,0,1,0)E.Position=UDim2.new(0,0,0,0)E.Parent=a local K=Instance.new("\070\114\097\109\101")K.Selectable=false K.Size=UDim2.new(1,0,1,0)K.Position=UDim2.new(0,0,0,0)K.ClipsDescendants=true K.BackgroundTransparency=1 K.Parent=A local F=Instance.new("\070\114\097\109\101")F.Selectable=false F.Name="\076\101\097\118\101\067\111\110\102\105\114\109\097\116\105\111\110\070\114\097\109\101"F.Size=UDim2.new(1,0,1,0)F.Position=UDim2.new(0,0,1,0)F.BackgroundTransparency=.6 F.BorderSizePixel=0 F.BackgroundColor3=Color3.new(0,0,0)F.Parent=K local d=Instance.new("\084\101\120\116\066\117\116\116\111\110")d.Selectable=false d.Size=UDim2.new(1,0,1,0)d.BackgroundTransparency=1 d.Text=""d.Parent=F local s=Instance.new("\084\101\120\116\066\117\116\116\111\110")s.Selectable=false s.Size=UDim2.new(.25,0,1,0)s.BackgroundTransparency=1 s.Font=ChatSettings.DefaultFont s.TextSize=18 s.TextStrokeTransparency=.75 s.Position=UDim2.new(0,0,0,0)s.TextColor3=Color3.new(0,1,0)s.Text="\067\111\110\102\105\114\109"s.Parent=F local U=s:Clone()U.Parent=F U.Position=UDim2.new(.75,0,0,0)U.TextColor3=Color3.new(1,0,0)U.Text="\067\097\110\099\101\108"local L=Instance.new("\084\101\120\116\076\097\098\101\108")L.Selectable=false L.Size=UDim2.new(.5,0,1,0)L.Position=UDim2.new(.25,0,0,0)L.BackgroundTransparency=1 L.TextColor3=Color3.new(1,1,1)L.TextStrokeTransparency=.75 L.Text="\076\101\097\118\101 \099\104\097\110\110\101\108 \060\088\088\062\063"L.Font=ChatSettings.DefaultFont L.TextSize=18 L.Parent=F local Z=Instance.new("\083\116\114\105\110\103\086\097\108\117\101")Z.Name="\076\101\097\118\101\084\097\114\103\101\116"Z.Parent=F local C=F.Position s.MouseButton1Click:connect(function()MessageSender:SendMessage(string.format("\047\108\101\097\118\101 \037\115",Z.Value),nil)F:TweenPosition(C,Enum.EasingDirection.Out,Enum.EasingStyle.Quad,.2,true)end)U.MouseButton1Click:connect(function()F:TweenPosition(C,Enum.EasingDirection.Out,Enum.EasingStyle.Quad,.2,true)end)local q=.7 local n=(1-q)/2 local p="\114\098\120\097\115\115\101\116\058\047\047\116\101\120\116\117\114\101\115\047\117\105\047\067\104\097\116\047\084\097\098\065\114\114\111\119\066\097\099\107\103\114\111\117\110\100\046\112\110\103"local t="\114\098\120\097\115\115\101\116\058\047\047\116\101\120\116\117\114\101\115\047\117\105\047\067\104\097\116\047\084\097\098\065\114\114\111\119\046\112\110\103"p="\114\098\120\097\115\115\101\116\105\100\058\047\047\052\055\049\054\051\048\049\057\057"t="\114\098\120\097\115\115\101\116\105\100\058\047\047\052\055\049\054\051\048\049\049\050"local h=Instance.new("\073\109\097\103\101\066\117\116\116\111\110",A)h.Selectable=ChatSettings.GamepadNavigationEnabled h.Name="\080\097\103\101\076\101\102\116\066\117\116\116\111\110"h.SizeConstraint=Enum.SizeConstraint.RelativeYY h.Size=UDim2.new(q,0,q,0)h.BackgroundTransparency=1 h.Position=UDim2.new(0,4,n,0)h.Visible=false h.Image=p local l=Instance.new("\073\109\097\103\101\076\097\098\101\108",h)l.Name="\065\114\114\111\119\076\097\098\101\108"l.BackgroundTransparency=1 l.Size=UDim2.new(.4,0,.4,0)l.Image=t local D=Instance.new("\070\114\097\109\101",A)D.Selectable=false D.BackgroundTransparency=1 D.Name="\080\111\115\105\116\105\111\110\097\108\072\101\108\112\101\114"D.Size=h.Size D.SizeConstraint=h.SizeConstraint D.Position=UDim2.new(1,0,n,0)local k=h:Clone()k.Parent=D k.Name="\080\097\103\101\082\105\103\104\116\066\117\116\116\111\110"k.Size=UDim2.new(1,0,1,0)k.SizeConstraint=Enum.SizeConstraint.RelativeXY k.Position=UDim2.new(-1,-4,0,0)local B=UDim2.new(.05,0,0,0)k.ArrowLabel.Position=UDim2.new(.3,0,.3,0)+B h.ArrowLabel.Position=UDim2.new(.3,0,.3,0)-B h.ArrowLabel.Rotation=180 y.GuiObject=A y.GuiObjects.BaseFrame=A y.GuiObjects.ScrollerSizer=a y.GuiObjects.ScrollerFrame=E y.GuiObjects.PageLeftButton=h y.GuiObjects.PageRightButton=k y.GuiObjects.LeaveConfirmationFrame=F y.GuiObjects.LeaveConfirmationNotice=L y.GuiObjects.PageLeftButtonArrow=h.ArrowLabel y.GuiObjects.PageRightButtonArrow=k.ArrowLabel y:AnimGuiObjects()h.MouseButton1Click:connect(function()y:ScrollChannelsFrame(-1)end)k.MouseButton1Click:connect(function()y:ScrollChannelsFrame(1)end)y:ScrollChannelsFrame(0)end function V.UpdateMessagePostedInChannel(y,V)local A=y:GetChannelTab(V)if A then A:UpdateMessagePostedInChannel()else warn("\067\104\097\110\110\101\108\115\084\097\098 \'"..(V.."\' \100\111\101\115 \110\111\116 \101\120\105\115\116\033"))end end function V.AddChannelTab(y,V)if y:GetChannelTab(V)then error("\067\104\097\110\110\101\108 \116\097\098 \'"..(V.."\'\097\108\114\101\097\100\121 \101\120\105\115\116\115\033"))end local A=moduleChannelsTab.new(V)A.GuiObject.Parent=y.GuiObjects.ScrollerFrame y.ChannelTabs[V:lower()]=A y.NumTabs=y.NumTabs+1 y:OrganizeChannelTabs()if ChatSettings.RightClickToLeaveChannelEnabled then A.NameTag.MouseButton2Click:connect(function()y.LeaveConfirmationNotice.Text=string.format("\076\101\097\118\101 \099\104\097\110\110\101\108 \037\115\063",A.ChannelName)y.LeaveConfirmationFrame.LeaveTarget.Value=A.ChannelName y.LeaveConfirmationFrame:TweenPosition(UDim2.new(0,0,0,0),Enum.EasingDirection.In,Enum.EasingStyle.Quad,.2,true)end)end return A end function V.RemoveChannelTab(y,V)if not y:GetChannelTab(V)then error("\067\104\097\110\110\101\108 \116\097\098 \'"..(V.."\'\100\111\101\115 \110\111\116 \101\120\105\115\116\033"))end local A=V:lower()y.ChannelTabs[A]:Destroy()y.ChannelTabs[A]=nil y.NumTabs=y.NumTabs-1 y:OrganizeChannelTabs()end function V.GetChannelTab(y,V)return y.ChannelTabs[V:lower()]end function V.OrganizeChannelTabs(V)local y={}table.insert(y,V:GetChannelTab(ChatSettings.GeneralChannelName))table.insert(y,V:GetChannelTab("\083\121\115\116\101\109"))for V,A in pairs(V.ChannelTabs)do if A.ChannelName~=ChatSettings.GeneralChannelName and A.ChannelName~="\083\121\115\116\101\109"then table.insert(y,A)end end for V,y in pairs(y)do y.GuiObject.Position=UDim2.new(V-1,0,0,0)end V.GuiObjects.ScrollerSizer.Size=UDim2.new(1/math.max(1,math.min(ChatSettings.ChannelsBarFullTabSize,V.NumTabs)),0,1,0)V:ScrollChannelsFrame(0)end function V.ResizeChannelTabText(y,V)for y,A in pairs(y.ChannelTabs)do A:SetTextSize(V)end end function V.ScrollChannelsFrame(y,V)if y.ScrollChannelsFrameLock then return end y.ScrollChannelsFrameLock=true local A=ChatSettings.ChannelsBarFullTabSize local j=y.CurPageNum+V if j<0 then j=0 elseif j>0 and j+A>y.NumTabs then j=y.NumTabs-A end y.CurPageNum=j local a=.15 local E=UDim2.new(-y.CurPageNum,0,0,0)y.GuiObjects.PageLeftButton.Visible=y.CurPageNum>0 y.GuiObjects.PageRightButton.Visible=y.CurPageNum+A<y.NumTabs if V==0 then y.ScrollChannelsFrameLock=false return end local function K()y.ScrollChannelsFrameLock=false end y:WaitUntilParentedCorrectly()y.GuiObjects.ScrollerFrame:TweenPosition(E,Enum.EasingDirection.InOut,Enum.EasingStyle.Quad,a,true,K)end function V.FadeOutBackground(y,V)for y,A in pairs(y.ChannelTabs)do A:FadeOutBackground(V)end y.AnimParams.Background_TargetTransparency=1 y.AnimParams.Background_NormalizedExptValue=CurveUtil:NormalizedDefaultExptValueInSeconds(V)end function V.FadeInBackground(y,V)for y,A in pairs(y.ChannelTabs)do A:FadeInBackground(V)end y.AnimParams.Background_TargetTransparency=.6 y.AnimParams.Background_NormalizedExptValue=CurveUtil:NormalizedDefaultExptValueInSeconds(V)end function V.FadeOutText(y,V)for y,A in pairs(y.ChannelTabs)do A:FadeOutText(V)end end function V.FadeInText(y,V)for y,A in pairs(y.ChannelTabs)do A:FadeInText(V)end end function V.AnimGuiObjects(V)V.GuiObjects.PageLeftButton.ImageTransparency=V.AnimParams.Background_CurrentTransparency V.GuiObjects.PageRightButton.ImageTransparency=V.AnimParams.Background_CurrentTransparency V.GuiObjects.PageLeftButtonArrow.ImageTransparency=V.AnimParams.Background_CurrentTransparency V.GuiObjects.PageRightButtonArrow.ImageTransparency=V.AnimParams.Background_CurrentTransparency end function V.InitializeAnimParams(V)V.AnimParams.Background_TargetTransparency=.6 V.AnimParams.Background_CurrentTransparency=.6 V.AnimParams.Background_NormalizedExptValue=CurveUtil:NormalizedDefaultExptValueInSeconds(0)end function V.Update(y,V)for y,A in pairs(y.ChannelTabs)do A:Update(V)end y.AnimParams.Background_CurrentTransparency=CurveUtil:Expt(y.AnimParams.Background_CurrentTransparency,y.AnimParams.Background_TargetTransparency,y.AnimParams.Background_NormalizedExptValue,V)y:AnimGuiObjects()end

local methods = {}
methods.__index = methods

function methods:CreateGuiObjects(targetParent)
	local BaseFrame = Instance.new("Frame")
	BaseFrame.Selectable = false
	BaseFrame.Size = UDim2.new(1, 0, 1, 0)
	BaseFrame.BackgroundTransparency = 1
	BaseFrame.Parent = targetParent

	local ScrollingBase = Instance.new("Frame")
	ScrollingBase.Selectable = false
	ScrollingBase.Name = "ScrollingBase"
	ScrollingBase.BackgroundTransparency = 1
	ScrollingBase.ClipsDescendants = true
	ScrollingBase.Size = UDim2.new(1, 0, 1, 0)
	ScrollingBase.Position = UDim2.new(0, 0, 0, 0)
	ScrollingBase.Parent = BaseFrame

	local ScrollerSizer = Instance.new("Frame")
	ScrollerSizer.Selectable = false
	ScrollerSizer.Name = "ScrollerSizer"
	ScrollerSizer.BackgroundTransparency = 1
	ScrollerSizer.Size = UDim2.new(1, 0, 1, 0)
	ScrollerSizer.Position = UDim2.new(0, 0, 0, 0)
	ScrollerSizer.Parent = ScrollingBase

	local ScrollerFrame = Instance.new("Frame")
	ScrollerFrame.Selectable = false
	ScrollerFrame.Name = "ScrollerFrame"
	ScrollerFrame.BackgroundTransparency = 1
	ScrollerFrame.Size = UDim2.new(1, 0, 1, 0)
	ScrollerFrame.Position = UDim2.new(0, 0, 0, 0)
	ScrollerFrame.Parent = ScrollerSizer

	local LeaveConfirmationFrameBase = Instance.new("Frame")
	LeaveConfirmationFrameBase.Selectable = false
	LeaveConfirmationFrameBase.Size = UDim2.new(1, 0, 1, 0)
	LeaveConfirmationFrameBase.Position = UDim2.new(0, 0, 0, 0)
	LeaveConfirmationFrameBase.ClipsDescendants = true
	LeaveConfirmationFrameBase.BackgroundTransparency = 1
	LeaveConfirmationFrameBase.Parent = BaseFrame

	local LeaveConfirmationFrame = Instance.new("Frame")
	LeaveConfirmationFrame.Selectable = false
	LeaveConfirmationFrame.Name = "LeaveConfirmationFrame"
	LeaveConfirmationFrame.Size = UDim2.new(1, 0, 1, 0)
	LeaveConfirmationFrame.Position = UDim2.new(0, 0, 1, 0)
	LeaveConfirmationFrame.BackgroundTransparency = 0.6
	LeaveConfirmationFrame.BorderSizePixel = 0
	LeaveConfirmationFrame.BackgroundColor3 = Color3.new(0, 0, 0)
	LeaveConfirmationFrame.Parent = LeaveConfirmationFrameBase

	local InputBlocker = Instance.new("TextButton")
	InputBlocker.Selectable = false
	InputBlocker.Size = UDim2.new(1, 0, 1, 0)
	InputBlocker.BackgroundTransparency = 1
	InputBlocker.Text = ""
	InputBlocker.Parent = LeaveConfirmationFrame

	local LeaveConfirmationButtonYes = Instance.new("TextButton")
	LeaveConfirmationButtonYes.Selectable = false
	LeaveConfirmationButtonYes.Size = UDim2.new(0.25, 0, 1, 0)
	LeaveConfirmationButtonYes.BackgroundTransparency = 1
	LeaveConfirmationButtonYes.Font = ChatSettings.DefaultFont
	LeaveConfirmationButtonYes.TextSize = 18
	LeaveConfirmationButtonYes.TextStrokeTransparency = 0.75
	LeaveConfirmationButtonYes.Position = UDim2.new(0, 0, 0, 0)
	LeaveConfirmationButtonYes.TextColor3 = Color3.new(0, 1, 0)
	LeaveConfirmationButtonYes.Text = "Confirm"
	LeaveConfirmationButtonYes.Parent = LeaveConfirmationFrame

	local LeaveConfirmationButtonNo = LeaveConfirmationButtonYes:Clone()
	LeaveConfirmationButtonNo.Parent = LeaveConfirmationFrame
	LeaveConfirmationButtonNo.Position = UDim2.new(0.75, 0, 0, 0)
	LeaveConfirmationButtonNo.TextColor3 = Color3.new(1, 0, 0)
	LeaveConfirmationButtonNo.Text = "Cancel"

	local LeaveConfirmationNotice = Instance.new("TextLabel")
	LeaveConfirmationNotice.Selectable = false
	LeaveConfirmationNotice.Size = UDim2.new(0.5, 0, 1, 0)
	LeaveConfirmationNotice.Position = UDim2.new(0.25, 0, 0, 0)
	LeaveConfirmationNotice.BackgroundTransparency = 1
	LeaveConfirmationNotice.TextColor3 = Color3.new(1, 1, 1)
	LeaveConfirmationNotice.TextStrokeTransparency = 0.75
	LeaveConfirmationNotice.Text = "Leave channel <XX>?"
	LeaveConfirmationNotice.Font = ChatSettings.DefaultFont
	LeaveConfirmationNotice.TextSize = 18
	LeaveConfirmationNotice.Parent = LeaveConfirmationFrame

	local LeaveTarget = Instance.new("StringValue")
	LeaveTarget.Name = "LeaveTarget"
	LeaveTarget.Parent = LeaveConfirmationFrame

	local outPos = LeaveConfirmationFrame.Position
	LeaveConfirmationButtonYes.MouseButton1Click:connect(function()
		MessageSender:SendMessage(string.format("/leave %s", LeaveTarget.Value), nil)
		LeaveConfirmationFrame:TweenPosition(outPos, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.2, true)
	end)
	LeaveConfirmationButtonNo.MouseButton1Click:connect(function()
		LeaveConfirmationFrame:TweenPosition(outPos, Enum.EasingDirection.Out, Enum.EasingStyle.Quad, 0.2, true)
	end)



	local scale = 0.7
	local scaleOther = (1 - scale) / 2
	local pageButtonImage = "rbxasset://textures/ui/Chat/TabArrowBackground.png"
	local pageButtonArrowImage = "rbxasset://textures/ui/Chat/TabArrow.png"

	--// ToDo: Remove these lines when the assets are put into trunk.
	--// These grab unchanging versions hosted on the site, and not from the content folder.
	pageButtonImage = "rbxassetid://471630199"
	pageButtonArrowImage = "rbxassetid://471630112"


	local PageLeftButton = Instance.new("ImageButton", BaseFrame)
	PageLeftButton.Selectable = ChatSettings.GamepadNavigationEnabled
	PageLeftButton.Name = "PageLeftButton"
	PageLeftButton.SizeConstraint = Enum.SizeConstraint.RelativeYY
	PageLeftButton.Size = UDim2.new(scale, 0, scale, 0)
	PageLeftButton.BackgroundTransparency = 1
	PageLeftButton.Position = UDim2.new(0, 4, scaleOther, 0)
	PageLeftButton.Visible = false
	PageLeftButton.Image = pageButtonImage
	local ArrowLabel = Instance.new("ImageLabel", PageLeftButton)
	ArrowLabel.Name = "ArrowLabel"
	ArrowLabel.BackgroundTransparency = 1
	ArrowLabel.Size = UDim2.new(0.4, 0, 0.4, 0)
	ArrowLabel.Image = pageButtonArrowImage

	local PageRightButtonPositionalHelper = Instance.new("Frame", BaseFrame)
	PageRightButtonPositionalHelper.Selectable = false
	PageRightButtonPositionalHelper.BackgroundTransparency = 1
	PageRightButtonPositionalHelper.Name = "PositionalHelper"
	PageRightButtonPositionalHelper.Size = PageLeftButton.Size
	PageRightButtonPositionalHelper.SizeConstraint = PageLeftButton.SizeConstraint
	PageRightButtonPositionalHelper.Position = UDim2.new(1, 0, scaleOther, 0)

	local PageRightButton = PageLeftButton:Clone()
	PageRightButton.Parent = PageRightButtonPositionalHelper
	PageRightButton.Name = "PageRightButton"
	PageRightButton.Size = UDim2.new(1, 0, 1, 0)
	PageRightButton.SizeConstraint = Enum.SizeConstraint.RelativeXY
	PageRightButton.Position = UDim2.new(-1, -4, 0, 0)

	local positionOffset = UDim2.new(0.05, 0, 0, 0)

	PageRightButton.ArrowLabel.Position = UDim2.new(0.3, 0, 0.3, 0) + positionOffset
	PageLeftButton.ArrowLabel.Position = UDim2.new(0.3, 0, 0.3, 0) - positionOffset
	PageLeftButton.ArrowLabel.Rotation = 180


	self.GuiObject = BaseFrame

	self.GuiObjects.BaseFrame = BaseFrame
	self.GuiObjects.ScrollerSizer = ScrollerSizer
	self.GuiObjects.ScrollerFrame = ScrollerFrame
	self.GuiObjects.PageLeftButton = PageLeftButton
	self.GuiObjects.PageRightButton = PageRightButton
	self.GuiObjects.LeaveConfirmationFrame = LeaveConfirmationFrame
	self.GuiObjects.LeaveConfirmationNotice = LeaveConfirmationNotice

	self.GuiObjects.PageLeftButtonArrow = PageLeftButton.ArrowLabel
	self.GuiObjects.PageRightButtonArrow = PageRightButton.ArrowLabel
	self:AnimGuiObjects()

	PageLeftButton.MouseButton1Click:connect(function() self:ScrollChannelsFrame(-1) end)
	PageRightButton.MouseButton1Click:connect(function() self:ScrollChannelsFrame(1) end)

	self:ScrollChannelsFrame(0)
end


function methods:UpdateMessagePostedInChannel(channelName)
	local tab = self:GetChannelTab(channelName)
	if (tab) then
		tab:UpdateMessagePostedInChannel()
	else
		warn("ChannelsTab '" .. channelName .. "' does not exist!")
	end
end

function methods:AddChannelTab(channelName)
	if (self:GetChannelTab(channelName)) then
		error("Channel tab '" .. channelName .. "'already exists!")
	end

	local tab = moduleChannelsTab.new(channelName)
	tab.GuiObject.Parent = self.GuiObjects.ScrollerFrame
	self.ChannelTabs[channelName:lower()] = tab

	self.NumTabs = self.NumTabs + 1
	self:OrganizeChannelTabs()

	if (ChatSettings.RightClickToLeaveChannelEnabled) then
		tab.NameTag.MouseButton2Click:connect(function()
			self.LeaveConfirmationNotice.Text = string.format("Leave channel %s?", tab.ChannelName)
			self.LeaveConfirmationFrame.LeaveTarget.Value = tab.ChannelName
			self.LeaveConfirmationFrame:TweenPosition(UDim2.new(0, 0, 0, 0), Enum.EasingDirection.In, Enum.EasingStyle.Quad, 0.2, true)
		end)
	end

	return tab
end

function methods:RemoveChannelTab(channelName)
	if (not self:GetChannelTab(channelName)) then
		error("Channel tab '" .. channelName .. "'does not exist!")
	end

	local indexName = channelName:lower()
	self.ChannelTabs[indexName]:Destroy()
	self.ChannelTabs[indexName] = nil

	self.NumTabs = self.NumTabs - 1
	self:OrganizeChannelTabs()
end

function methods:GetChannelTab(channelName)
	return self.ChannelTabs[channelName:lower()]
end

function methods:OrganizeChannelTabs()
	local order = {}

	table.insert(order, self:GetChannelTab(ChatSettings.GeneralChannelName))
	table.insert(order, self:GetChannelTab("System"))

	for tabIndexName, tab in pairs(self.ChannelTabs) do
		if (tab.ChannelName ~= ChatSettings.GeneralChannelName and tab.ChannelName ~= "System") then
			table.insert(order, tab)
		end
	end

	for index, tab in pairs(order) do
		tab.GuiObject.Position = UDim2.new(index - 1, 0, 0, 0)
	end

	--// Dynamic tab resizing
	self.GuiObjects.ScrollerSizer.Size = UDim2.new(1 / math.max(1, math.min(ChatSettings.ChannelsBarFullTabSize, self.NumTabs)), 0, 1, 0)

	self:ScrollChannelsFrame(0)
end

function methods:ResizeChannelTabText(textSize)
	for i, tab in pairs(self.ChannelTabs) do
		tab:SetTextSize(textSize)
	end
end

function methods:ScrollChannelsFrame(dir)
	if (self.ScrollChannelsFrameLock) then return end
	self.ScrollChannelsFrameLock = true

	local tabNumber = ChatSettings.ChannelsBarFullTabSize

	local newPageNum = self.CurPageNum + dir
	if (newPageNum < 0) then
		newPageNum = 0
	elseif (newPageNum > 0 and newPageNum + tabNumber > self.NumTabs) then
		newPageNum = self.NumTabs - tabNumber
	end

	self.CurPageNum = newPageNum

	local tweenTime = 0.15
	local endPos = UDim2.new(-self.CurPageNum, 0, 0, 0)

	self.GuiObjects.PageLeftButton.Visible = (self.CurPageNum > 0)
	self.GuiObjects.PageRightButton.Visible = (self.CurPageNum + tabNumber < self.NumTabs)

	if dir == 0 then
		self.ScrollChannelsFrameLock = false
		return
	end

	local function UnlockFunc()
		self.ScrollChannelsFrameLock = false
	end

	self:WaitUntilParentedCorrectly()

	self.GuiObjects.ScrollerFrame:TweenPosition(endPos, Enum.EasingDirection.InOut, Enum.EasingStyle.Quad, tweenTime, true, UnlockFunc)
end

function methods:FadeOutBackground(duration)
	for channelName, channelObj in pairs(self.ChannelTabs) do
		channelObj:FadeOutBackground(duration)
	end

	self.AnimParams.Background_TargetTransparency = 1
	self.AnimParams.Background_NormalizedExptValue = CurveUtil:NormalizedDefaultExptValueInSeconds(duration)
end

function methods:FadeInBackground(duration)
	for channelName, channelObj in pairs(self.ChannelTabs) do
		channelObj:FadeInBackground(duration)
	end

	self.AnimParams.Background_TargetTransparency = 0.6
	self.AnimParams.Background_NormalizedExptValue = CurveUtil:NormalizedDefaultExptValueInSeconds(duration)
end

function methods:FadeOutText(duration)
	for channelName, channelObj in pairs(self.ChannelTabs) do
		channelObj:FadeOutText(duration)
	end
end

function methods:FadeInText(duration)
	for channelName, channelObj in pairs(self.ChannelTabs) do
		channelObj:FadeInText(duration)
	end
end

function methods:AnimGuiObjects()
	self.GuiObjects.PageLeftButton.ImageTransparency = self.AnimParams.Background_CurrentTransparency
	self.GuiObjects.PageRightButton.ImageTransparency = self.AnimParams.Background_CurrentTransparency
	self.GuiObjects.PageLeftButtonArrow.ImageTransparency = self.AnimParams.Background_CurrentTransparency
	self.GuiObjects.PageRightButtonArrow.ImageTransparency = self.AnimParams.Background_CurrentTransparency
end

function methods:InitializeAnimParams()
	self.AnimParams.Background_TargetTransparency = 0.6
	self.AnimParams.Background_CurrentTransparency = 0.6
	self.AnimParams.Background_NormalizedExptValue = CurveUtil:NormalizedDefaultExptValueInSeconds(0)
end

function methods:Update(dtScale)
	for channelName, channelObj in pairs(self.ChannelTabs) do
		channelObj:Update(dtScale)
	end

	self.AnimParams.Background_CurrentTransparency = CurveUtil:Expt(
			self.AnimParams.Background_CurrentTransparency,
			self.AnimParams.Background_TargetTransparency,
			self.AnimParams.Background_NormalizedExptValue,
			dtScale
	)

	self:AnimGuiObjects()
end
