@quenty/snackbar 11.3.0 → 11.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,22 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [11.4.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/snackbar@11.3.0...@quenty/snackbar@11.4.0) (2024-05-09)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Fix .package-lock.json replicating in packages ([75d0efe](https://github.com/Quenty/NevermoreEngine/commit/75d0efeef239f221d93352af71a5b3e930ec23c5))
12
+
13
+
14
+ ### Features
15
+
16
+ * Refactor snackbar package to new snackbar system ([6f5113b](https://github.com/Quenty/NevermoreEngine/commit/6f5113b3ff1b637f40abb17160ab61788245a05d))
17
+
18
+
19
+
20
+
21
+
6
22
  # [11.3.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/snackbar@11.2.0...@quenty/snackbar@11.3.0) (2024-04-28)
7
23
 
8
24
 
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "snackbar",
3
+ "globIgnorePaths": [ "**/.package-lock.json" ],
3
4
  "tree": {
4
5
  "$path": "src"
5
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/snackbar",
3
- "version": "11.3.0",
3
+ "version": "11.4.0",
4
4
  "description": "Snackbars provide lightweight feedback on an operation at the base of the screen. They automatically disappear after a timeout or user interaction. There can only be one on the screen at a time.",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -25,13 +25,33 @@
25
25
  "Quenty"
26
26
  ],
27
27
  "dependencies": {
28
- "@quenty/loader": "^10.2.0",
29
- "@quenty/maid": "^3.1.0",
30
- "@quenty/math": "^2.6.0",
31
- "@quenty/qgui": "^2.2.1"
28
+ "@quenty/baseobject": "^10.3.0",
29
+ "@quenty/basicpane": "^13.3.0",
30
+ "@quenty/blend": "^12.3.0",
31
+ "@quenty/buttondragmodel": "^1.1.0",
32
+ "@quenty/buttonhighlightmodel": "file:../ButtonHighlightModel",
33
+ "@quenty/ducktype": "^5.3.0",
34
+ "@quenty/genericscreenguiprovider": "^13.5.0",
35
+ "@quenty/inputobjectutils": "^4.4.0",
36
+ "@quenty/lipsum": "^14.3.0",
37
+ "@quenty/loader": "^10.3.0",
38
+ "@quenty/maid": "^3.2.0",
39
+ "@quenty/math": "^2.7.0",
40
+ "@quenty/promise": "^10.3.0",
41
+ "@quenty/promisemaid": "^5.3.0",
42
+ "@quenty/promptqueue": "^1.1.0",
43
+ "@quenty/qgui": "^2.3.0",
44
+ "@quenty/rx": "^13.3.0",
45
+ "@quenty/servicebag": "^11.4.0",
46
+ "@quenty/table": "^3.5.0",
47
+ "@quenty/textserviceutils": "^13.3.0",
48
+ "@quenty/transitionmodel": "^7.3.0",
49
+ "@quenty/utf8": "^2.2.0",
50
+ "@quenty/valueobject": "^13.3.0",
51
+ "@quentystudios/t": "^3.0.1"
32
52
  },
33
53
  "publishConfig": {
34
54
  "access": "public"
35
55
  },
36
- "gitHead": "1f65df4adb6f3c04fb25d70bfa93f0f7c332c143"
56
+ "gitHead": "3fd5cdca3128bf34c8d9dfae1e92d62533b6e6f5"
37
57
  }
@@ -0,0 +1,367 @@
1
+ --[=[
2
+ Snackbars provide lightweight feedback on an operation
3
+ at the base of the screen. They automatically disappear
4
+ after a timeout or user interaction. There can only be
5
+ one on the screen at a time.
6
+
7
+ @class Snackbar
8
+ ]=]
9
+
10
+ local require = require(script.Parent.loader).load(script)
11
+
12
+ local Blend = require("Blend")
13
+ local ButtonDragModel = require("ButtonDragModel")
14
+ local ButtonHighlightModel = require("ButtonHighlightModel")
15
+ local DuckTypeUtils = require("DuckTypeUtils")
16
+ local Math = require("Math")
17
+ local PromiseMaidUtils = require("PromiseMaidUtils")
18
+ local PromiseUtils = require("PromiseUtils")
19
+ local SnackbarOptionUtils = require("SnackbarOptionUtils")
20
+ local SpringTransitionModel = require("SpringTransitionModel")
21
+ local TransitionModel = require("TransitionModel")
22
+ local UTF8 = require("UTF8")
23
+ local ValueObject = require("ValueObject")
24
+ local SpringObject = require("SpringObject")
25
+ local Table = require("Table")
26
+
27
+ local SHADOW_RADIUS = 2
28
+ local CORNER_RADIUS = 2
29
+ local PADDING_FROM_BOTTOM = 10
30
+
31
+ local DRAG_DISTANCE_TO_HIDE = 48
32
+ local DURATION = 3
33
+ local SHOW_POSITION = UDim2.new(1, 0, 1, 0)
34
+ local HIDE_POSITION = UDim2.new(1, 0, 1, 48)
35
+
36
+ local PADDING_X = 24
37
+ local DEFAULT_TEXT_COLOR = Color3.fromRGB(78, 205, 196)
38
+
39
+ local SnackbarDragDirections = Table.readonly({
40
+ HORIZONTAL = "horizontal";
41
+ VERTICAL = "vertical";
42
+ NONE = "none";
43
+ })
44
+
45
+ local Snackbar = setmetatable({}, TransitionModel)
46
+ Snackbar.ClassName = "Snackbar"
47
+ Snackbar.__index = Snackbar
48
+
49
+ function Snackbar.new(text, options)
50
+ assert(SnackbarOptionUtils.isSnackbarOptions(options) or options == nil, "Bad options")
51
+ options = options or SnackbarOptionUtils.createSnackbarOptions({})
52
+
53
+ local self = setmetatable(TransitionModel.new(), Snackbar)
54
+
55
+ self._text = self._maid:Add(ValueObject.new(text, "string"))
56
+ self._backgroundColor = self._maid:Add(ValueObject.new(Color3.new(0.196, 0.196, 0.196), "Color3"))
57
+
58
+ self._percentVisibleModel = self._maid:Add(SpringTransitionModel.new())
59
+ self._percentVisibleModel:SetEpsilon(1e-2)
60
+ self._percentVisibleModel:SetSpeed(50)
61
+ self._percentVisibleModel:BindToPaneVisbility(self)
62
+
63
+ self._dragSpring = self._maid:Add(SpringObject.new(Vector2.zero, 30))
64
+
65
+ self._positionSpringModel = self._maid:Add(SpringTransitionModel.new(SHOW_POSITION, HIDE_POSITION))
66
+ self._positionSpringModel:SetEpsilon(1e-2)
67
+ self._positionSpringModel:BindToPaneVisbility(self)
68
+
69
+ self._dragModel = self._maid:Add(ButtonDragModel.new())
70
+ self._dragModel:SetClampWithinButton(false)
71
+
72
+ self:SetPromiseShow(function()
73
+ return self._percentVisibleModel:PromiseShow()
74
+ end)
75
+ self:SetPromiseHide(function()
76
+ return self._percentVisibleModel:PromiseHide()
77
+ end)
78
+
79
+ self._maid:GiveTask(self:_render():Subscribe(function(gui)
80
+ self.Gui = gui
81
+ end))
82
+
83
+ if options and options.CallToAction then
84
+ self._maid:GiveTask(self:_renderCallToAction(options.CallToAction):Subscribe(function(button)
85
+ button.Parent = self._callToActionContainer
86
+ end))
87
+ end
88
+
89
+ self:_setupDragging()
90
+
91
+ return self
92
+ end
93
+
94
+ function Snackbar.isSnackbar(value)
95
+ return DuckTypeUtils.isImplementation(Snackbar, value)
96
+ end
97
+
98
+ function Snackbar:PromiseSustain()
99
+ local promise = PromiseUtils.delayed(DURATION)
100
+
101
+ PromiseMaidUtils.whilePromise(promise, function(maid)
102
+ maid:GiveTask(self.VisibleChanged:Connect(function(isVisible)
103
+ if not isVisible then
104
+ promise:Resolve()
105
+ end
106
+ end))
107
+ end)
108
+
109
+ return promise
110
+ end
111
+
112
+ function Snackbar:_setupDragging()
113
+ self._maid:GiveTask(self._dragSpring:ObserveTarget():Subscribe(function()
114
+ self:_updateHideFromDragTarget()
115
+ end))
116
+ self._maid:GiveTask(self.Gui:GetPropertyChangedSignal("AbsoluteSize"):Connect(function()
117
+ self:_updateHideFromDragTarget()
118
+ end))
119
+
120
+ self._maid:GiveTask(self._dragModel:ObserveIsDraggingBrio():Subscribe(function(brio)
121
+ if brio:IsDead() then
122
+ return
123
+ end
124
+
125
+ local maid = brio:ToMaidAndValue()
126
+ local dragDirection = SnackbarDragDirections.NONE
127
+
128
+ maid:GiveTask(self._dragModel:ObserveDragDelta():Subscribe(function(delta)
129
+ if not delta then
130
+ dragDirection = SnackbarDragDirections.NONE
131
+ return
132
+ end
133
+
134
+ if delta.magnitude == 0 then
135
+ return
136
+ end
137
+
138
+ if dragDirection == SnackbarDragDirections.VERTICAL then
139
+ self._dragSpring:SetTarget(Vector2.new(0, delta.y), true)
140
+ elseif dragDirection == SnackbarDragDirections.HORIZONTAL then
141
+ self._dragSpring:SetTarget(Vector2.new(delta.x, 0), true)
142
+ else
143
+ if math.abs(delta.x) > math.abs(delta.y) then
144
+ dragDirection = SnackbarDragDirections.HORIZONTAL
145
+ self._dragSpring:SetTarget(Vector2.new(delta.x, 0), true)
146
+ else
147
+ dragDirection = SnackbarDragDirections.VERTICAL
148
+ self._dragSpring:SetTarget(Vector2.new(0, delta.y), true)
149
+ end
150
+ end
151
+ end))
152
+
153
+ maid:GiveTask(function()
154
+ if self._dragSpring.Target.magnitude > 0.5*DRAG_DISTANCE_TO_HIDE then
155
+ self:Hide()
156
+ else
157
+ self._dragSpring:SetTarget(Vector2.zero)
158
+ end
159
+ end)
160
+ end))
161
+
162
+ self:_updateHideFromDragTarget()
163
+ end
164
+
165
+ function Snackbar:_updateHideFromDragTarget(doNotAnimate)
166
+ local target = self._dragSpring.Target
167
+ local guiSize = self.Gui.AbsoluteSize
168
+ local hideTarget
169
+ if target.y > 0 then
170
+ -- Down
171
+ hideTarget = SHOW_POSITION + UDim2.new(0, 0, 0, guiSize.Y)
172
+ elseif target.y < 0 then
173
+ -- Up
174
+ hideTarget = SHOW_POSITION + UDim2.new(0, 0, 0, -guiSize.Y)
175
+ elseif target.x < 0 then
176
+ hideTarget = SHOW_POSITION + UDim2.new(0, -guiSize.X, 0, 0)
177
+ elseif target.x > 0 then
178
+ hideTarget = SHOW_POSITION + UDim2.new(0, guiSize.X, 0, 0)
179
+ else
180
+ hideTarget = SHOW_POSITION + UDim2.new(0, 0, 0, guiSize.Y)
181
+ end
182
+
183
+ self._positionSpringModel:SetHideTarget(hideTarget, doNotAnimate)
184
+ end
185
+
186
+
187
+ function Snackbar:_render()
188
+ local percentDragHidden = Blend.Computed(self._dragSpring:Observe(), function(value)
189
+ return math.clamp(Math.map(value.magnitude, 0, DRAG_DISTANCE_TO_HIDE, 0, 1), 0, 1)
190
+ end)
191
+ self._computedTransparency = Blend.Computed(self._percentVisibleModel:Observe(), percentDragHidden, function(visible, dragHidden)
192
+ return Math.map(visible, 0, 1, 1, dragHidden)
193
+ end)
194
+
195
+ return Blend.New "Frame" {
196
+ ZIndex = 1;
197
+ Name = "Snackbar";
198
+ Size = UDim2.new(0, 0, 0, 0);
199
+ AutomaticSize = Enum.AutomaticSize.XY;
200
+ Position = Blend.Computed(self._positionSpringModel:Observe(), self._dragSpring:Observe(), function(position, dragPosition)
201
+ return position + UDim2.fromOffset(dragPosition.x, dragPosition.y)
202
+ end);
203
+ AnchorPoint = Vector2.new(1, 1);
204
+ BackgroundTransparency = 1;
205
+
206
+ Blend.New "UIPadding" {
207
+ PaddingTop = UDim.new(0, PADDING_FROM_BOTTOM);
208
+ PaddingBottom = UDim.new(0, PADDING_FROM_BOTTOM);
209
+ PaddingLeft = UDim.new(0, PADDING_FROM_BOTTOM);
210
+ PaddingRight = UDim.new(0, PADDING_FROM_BOTTOM);
211
+ };
212
+
213
+ Blend.New "UIListLayout" {
214
+ FillDirection = Enum.FillDirection.Horizontal;
215
+ };
216
+
217
+ Blend.New "ImageButton" {
218
+ Size = UDim2.new(0, 0, 0, 0);
219
+ AnchorPoint = Vector2.new(1, 1);
220
+ AutomaticSize = Enum.AutomaticSize.XY;
221
+ BackgroundTransparency = 1;
222
+ AutoButtonColor = false;
223
+
224
+ [Blend.Instance] = function(gui)
225
+ self._mainButton = gui
226
+ self._dragModel:SetButton(gui)
227
+ end;
228
+
229
+ Blend.New "UICorner" {
230
+ CornerRadius = UDim.new(0, CORNER_RADIUS);
231
+ };
232
+
233
+ Blend.New "UIListLayout" {
234
+ FillDirection = Enum.FillDirection.Horizontal;
235
+ };
236
+
237
+
238
+ Blend.New "Folder" {
239
+ Name = "BackingFolder";
240
+
241
+ Blend.New "ImageLabel" {
242
+ Name = "Shadow";
243
+ ZIndex = 1;
244
+ Image = "rbxassetid://191838004";
245
+ AnchorPoint = Vector2.new(0.5, 0.5);
246
+ Position = UDim2.fromScale(0.5, 0.5);
247
+ ImageRectSize = Vector2.new(150, 150);
248
+ ScaleType = Enum.ScaleType.Slice;
249
+ SliceCenter = Rect.new(50, 50, 100, 100);
250
+ SliceScale = (2*SHADOW_RADIUS + CORNER_RADIUS)/50;
251
+ BackgroundTransparency = 1;
252
+ Size = UDim2.new(1, 2*SHADOW_RADIUS, 1, 2*SHADOW_RADIUS);
253
+ ImageTransparency = Blend.Computed(self._computedTransparency, function(value)
254
+ return Math.map(value, 0, 1, 0.75, 1)
255
+ end);
256
+ };
257
+ };
258
+
259
+ Blend.New "Frame" {
260
+ Name = "Container";
261
+ AutomaticSize = Enum.AutomaticSize.XY;
262
+ Size = UDim2.new(0, 0, 0, 0);
263
+ ZIndex = 2;
264
+ BackgroundColor3 = self._backgroundColor:Observe();
265
+ BackgroundTransparency = self._computedTransparency;
266
+
267
+ Blend.New "UISizeConstraint" {
268
+ MaxSize = Vector2.new(700, 48*2);
269
+ MinSize = Vector2.new(100, 0);
270
+ };
271
+
272
+ [Blend.Instance] = function(gui)
273
+ self._callToActionContainer = gui
274
+ end;
275
+
276
+ Blend.New "UICorner" {
277
+ CornerRadius = UDim.new(0, CORNER_RADIUS);
278
+ };
279
+
280
+ Blend.New "UIListLayout" {
281
+ FillDirection = Enum.FillDirection.Horizontal;
282
+ HorizontalAlignment = Enum.HorizontalAlignment.Left;
283
+ VerticalAlignment = Enum.VerticalAlignment.Center;
284
+ Padding = UDim.new(0, PADDING_X);
285
+ };
286
+
287
+ Blend.New "UIPadding" {
288
+ PaddingTop = UDim.new(0, 15);
289
+ PaddingBottom = UDim.new(0, 15);
290
+ PaddingLeft = UDim.new(0, PADDING_X);
291
+ PaddingRight = UDim.new(0, PADDING_X);
292
+ };
293
+
294
+
295
+ Blend.New "TextLabel" {
296
+ Name = "SnackbarLabel";
297
+ LayoutOrder = 1;
298
+ BackgroundTransparency = 1;
299
+ AutomaticSize = Enum.AutomaticSize.XY;
300
+ TextColor3 = Color3.new(1, 1, 1);
301
+ Size = UDim2.new(0, 0, 0, 0);
302
+ Position = UDim2.new(0, 0, 0, 18);
303
+ TextXAlignment = Enum.TextXAlignment.Left;
304
+ TextYAlignment = Enum.TextYAlignment.Center;
305
+ BorderSizePixel = 0;
306
+ Font = Enum.Font.SourceSans;
307
+ Text = self._text:Observe();
308
+ TextWrapped = false;
309
+ TextTransparency = Blend.Computed(self._computedTransparency, function(value)
310
+ return Math.map(value, 0, 1, 0.13, 1)
311
+ end);
312
+ TextSize = 18;
313
+
314
+ [Blend.Instance] = function(gui)
315
+ self._textLabel = gui
316
+ end;
317
+ };
318
+ };
319
+ }
320
+ }
321
+ end
322
+
323
+ function Snackbar:_renderCallToAction(callToAction)
324
+ local callToActionText = ""
325
+ local onClick = nil
326
+ if type(callToAction) == "string" then
327
+ callToActionText = callToAction
328
+ else
329
+ callToActionText = tostring(callToAction.Text)
330
+ onClick = callToAction.OnClick
331
+ end
332
+
333
+ local buttonModel = self._maid:Add(ButtonHighlightModel.new())
334
+
335
+ return Blend.New "TextButton" {
336
+ Name = "CallToActionButton";
337
+ AnchorPoint = Vector2.new(1, 0.5);
338
+ LayoutOrder = 2;
339
+ BackgroundTransparency = 1;
340
+ Position = UDim2.new(1, 0, 0.5, 0);
341
+ AutomaticSize = Enum.AutomaticSize.X;
342
+ Size = UDim2.new(0, 0, 0, 18);
343
+ Text = UTF8.upper(callToActionText);
344
+ Font = Enum.Font.SourceSans;
345
+ FontSize = self._textLabel.FontSize;
346
+ TextXAlignment = Enum.TextXAlignment.Right;
347
+ TextColor3 = Blend.Computed(buttonModel:ObservePercentHighlighted(), function(percent)
348
+ local scale = Math.map(percent, 0, 1, 0, 0.2)
349
+ return DEFAULT_TEXT_COLOR:Lerp(Color3.new(0, 0, 0), scale)
350
+ end);
351
+ TextTransparency = self._computedTransparency;
352
+
353
+ [Blend.Instance] = function(gui)
354
+ buttonModel:SetButton(gui)
355
+ end;
356
+
357
+ [Blend.OnEvent "Activated"] = function()
358
+ self:Hide()
359
+
360
+ if onClick then
361
+ onClick()
362
+ end
363
+ end;
364
+ }
365
+ end
366
+
367
+ return Snackbar
@@ -0,0 +1,11 @@
1
+ --[=[
2
+ @class SnackbarScreenGuiProvider
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local GenericScreenGuiProvider = require("GenericScreenGuiProvider")
8
+
9
+ return GenericScreenGuiProvider.new({
10
+ SNACKBAR = 0;
11
+ })
@@ -5,7 +5,11 @@
5
5
 
6
6
  local require = require(script.Parent.loader).load(script)
7
7
 
8
- local DraggableSnackbar = require("DraggableSnackbar")
8
+ local Snackbar = require("Snackbar")
9
+ local SnackbarScreenGuiProvider = require("SnackbarScreenGuiProvider")
10
+ local Maid = require("Maid")
11
+ local SnackbarOptionUtils = require("SnackbarOptionUtils")
12
+ local PromptQueue = require("PromptQueue")
9
13
 
10
14
  local SnackbarServiceClient = {}
11
15
  SnackbarServiceClient.ServiceName = "SnackbarServiceClient"
@@ -13,8 +17,12 @@ SnackbarServiceClient.ServiceName = "SnackbarServiceClient"
13
17
  function SnackbarServiceClient:Init(serviceBag)
14
18
  assert(not self._serviceBag, "Already initialized")
15
19
  self._serviceBag = assert(serviceBag, "No serviceBag")
20
+ self._maid = Maid.new()
16
21
 
17
- self._currentSnackbar = nil
22
+ self._snackbarScreenGuiProvider = self._serviceBag:GetService(SnackbarScreenGuiProvider)
23
+ self._screenGui = self._maid:Add(self._snackbarScreenGuiProvider:Get("SNACKBAR"))
24
+
25
+ self._queue = self._maid:Add(PromptQueue.new())
18
26
  end
19
27
 
20
28
  --[=[
@@ -29,54 +37,50 @@ function SnackbarServiceClient:SetScreenGui(screenGui)
29
37
  return self
30
38
  end
31
39
 
32
- -- Automatically makes a snackbar and shows it
33
- -- @param text to show
34
- -- @param[opt] options
35
- --[[
36
- If options are included, in this format, a call to action will be presented to the player
37
- options = {
38
- CallToAction = {
39
- Text = "Action";
40
- OnClick = function() end;
41
- };
40
+ --[=[
41
+ Makes a snackbar and shows it to the user
42
+
43
+ If options are included, in this format, a call to action will be presented to the player
44
+
45
+ ```
46
+ {
47
+ CallToAction = {
48
+ Text = "Action";
49
+ OnClick = function() end;
42
50
  };
43
- ]]
51
+ };
52
+ ```
53
+
54
+ @param text string
55
+ @param options SnackbarOptions
56
+ ]=]
44
57
  function SnackbarServiceClient:ShowSnackbar(text, options)
45
58
  assert(type(text) == "string", "text must be a string")
59
+ assert(SnackbarOptionUtils.isSnackbarOptions(options) or options == nil, "Bad snackbarOptions")
46
60
 
47
- local snackbar = DraggableSnackbar.new(self._screenGui, text, true, options)
48
- self:_showSnackbar(snackbar)
61
+ local snackbar = Snackbar.new(text, options)
62
+ snackbar.Gui.Parent = self._screenGui
63
+
64
+ self._queue:HideCurrent()
65
+
66
+ self._maid:GivePromise(self._queue:Queue(snackbar))
67
+ :Finally(function()
68
+ snackbar:Destroy()
69
+ end)
49
70
 
50
71
  return snackbar
51
72
  end
52
73
 
53
- function SnackbarServiceClient:_showSnackbar(snackbar)
54
- assert(snackbar, "Must send a snackbar")
55
-
56
- if self._currentSnackbar == snackbar and self._currentSnackbar:IsVisible() then
57
- snackbar:Dismiss()
58
- else
59
- local dismissedSnackbar = false
60
-
61
- if self._currentSnackbar then
62
- if self._currentSnackbar:IsVisible() then
63
- self._currentSnackbar:Dismiss()
64
- self._currentSnackbar = nil
65
- dismissedSnackbar = true
66
- end
67
- end
68
-
69
- self._currentSnackbar = snackbar
70
- if dismissedSnackbar then
71
- task.delay(snackbar.FadeTime, function()
72
- if self._currentSnackbar == snackbar then
73
- snackbar:Show()
74
- end
75
- end)
76
- else
77
- snackbar:Show()
78
- end
79
- end
74
+ function SnackbarServiceClient:HideCurrent(doNotAnimate)
75
+ return self._queue:HideCurrent(doNotAnimate)
76
+ end
77
+
78
+ function SnackbarServiceClient:ClearQueue(doNotAnimate)
79
+ self._queue:Clear(doNotAnimate)
80
+ end
81
+
82
+ function SnackbarServiceClient:Destroy()
83
+ self._maid:DoCleaning()
80
84
  end
81
85
 
82
86
  return SnackbarServiceClient
@@ -0,0 +1,98 @@
1
+ --[[
2
+ @class snackbarServiceClient.story
3
+ ]]
4
+
5
+ local require = require(game:GetService("ServerScriptService"):FindFirstChild("LoaderUtils", true).Parent).bootstrapStory(script)
6
+
7
+ local Maid = require("Maid")
8
+ local ServiceBag = require("ServiceBag")
9
+ local SnackbarServiceClient = require("SnackbarServiceClient")
10
+ local ScreenGuiService = require("ScreenGuiService")
11
+ local LipsumUtils = require("LipsumUtils")
12
+ local Blend = require("Blend")
13
+
14
+ return function(target)
15
+ local maid = Maid.new()
16
+ local serviceBag = maid:Add(ServiceBag.new())
17
+
18
+ local snackbarServiceClient = serviceBag:GetService(SnackbarServiceClient)
19
+ maid:GiveTask(serviceBag:GetService(ScreenGuiService):SetGuiParent(target))
20
+
21
+ serviceBag:Init()
22
+ serviceBag:Start()
23
+
24
+ local function showSnackBar()
25
+ snackbarServiceClient:ShowSnackbar(LipsumUtils.sentence(10), {
26
+ CallToAction = {
27
+ Text = LipsumUtils.word();
28
+ OnClick = function()
29
+ print("Activated action")
30
+ end;
31
+ }
32
+ })
33
+ end
34
+
35
+ local function button(props)
36
+ return Blend.New "TextButton" {
37
+ AutomaticSize = Enum.AutomaticSize.XY;
38
+ AutoButtonColor = true;
39
+ Text = props.Text;
40
+ [Blend.OnEvent "Activated"] = props.OnActivated;
41
+
42
+ Blend.New "UIPadding" {
43
+ PaddingTop = UDim.new(0, 10);
44
+ PaddingBottom = UDim.new(0, 10);
45
+ PaddingLeft = UDim.new(0, 10);
46
+ PaddingRight = UDim.new(0, 10);
47
+ };
48
+
49
+ Blend.New "UICorner" {
50
+ CornerRadius = UDim.new(0, 5);
51
+ }
52
+ };
53
+ end
54
+
55
+ showSnackBar()
56
+
57
+ maid:GiveTask(Blend.mount(target, {
58
+ Blend.New "Frame" {
59
+ AutomaticSize = Enum.AutomaticSize.XY;
60
+ AnchorPoint = Vector2.new(0.5, 0);
61
+ Position = UDim2.fromScale(0.5, 0);
62
+ BackgroundTransparency = 1;
63
+
64
+ Blend.New "UIPadding" {
65
+ PaddingTop = UDim.new(0, 5);
66
+ PaddingBottom = UDim.new(0, 5);
67
+ PaddingLeft = UDim.new(0, 5);
68
+ PaddingRight = UDim.new(0, 5);
69
+ };
70
+
71
+ Blend.New "UIListLayout" {
72
+ FillDirection = Enum.FillDirection.Horizontal;
73
+ Padding = UDim.new(0, 5);
74
+ };
75
+
76
+ button({
77
+ Text = "Show snackbar";
78
+ OnActivated = showSnackBar;
79
+ });
80
+ button({
81
+ Text = "Clear queue";
82
+ OnActivated = function()
83
+ snackbarServiceClient:ClearQueue()
84
+ end;
85
+ });
86
+ button({
87
+ Text = "Hide current";
88
+ OnActivated = function()
89
+ snackbarServiceClient:HideCurrent()
90
+ end;
91
+ });
92
+ };
93
+ }))
94
+
95
+ return function()
96
+ maid:DoCleaning()
97
+ end
98
+ end
@@ -0,0 +1,17 @@
1
+ --[=[
2
+ @class SnackbarService
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local SnackbarService = {}
8
+ SnackbarService.ServiceName = "SnackbarService"
9
+
10
+ function SnackbarService:Init(serviceBag)
11
+ assert(not self._serviceBag, "Already initialized")
12
+ self._serviceBag = assert(serviceBag, "No serviceBag")
13
+
14
+
15
+ end
16
+
17
+ return SnackbarService
@@ -0,0 +1,25 @@
1
+ --[=[
2
+ @class SnackbarOptionUtils
3
+
4
+ ]=]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local t = require("t")
9
+
10
+ local SnackbarOptionUtils = {}
11
+
12
+ function SnackbarOptionUtils.createSnackbarOptions(options)
13
+ assert(SnackbarOptionUtils.isSnackbarOptions(options))
14
+
15
+ return options
16
+ end
17
+
18
+ SnackbarOptionUtils.isSnackbarOptions = t.interface({
19
+ CallToAction = t.optional(t.union(t.string, t.interface({
20
+ Text = t.string;
21
+ OnClick = t.optional(t.callback);
22
+ })));
23
+ })
24
+
25
+ return SnackbarOptionUtils
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "SnackbarTest",
3
+ "globIgnorePaths": [ "**/.package-lock.json" ],
4
+ "tree": {
5
+ "$className": "DataModel",
6
+ "ServerScriptService": {
7
+ "snackbar": {
8
+ "$path": ".."
9
+ },
10
+ "Script": {
11
+ "$path": "scripts/Server"
12
+ }
13
+ },
14
+ "StarterPlayer": {
15
+ "StarterPlayerScripts": {
16
+ "Main": {
17
+ "$path": "scripts/Client"
18
+ }
19
+ }
20
+ }
21
+ }
22
+ }
@@ -0,0 +1,31 @@
1
+ --[[
2
+ @class ClientMain
3
+ ]]
4
+ local loader = game:GetService("ReplicatedStorage"):WaitForChild("snackbar"):WaitForChild("loader")
5
+ local require = require(loader).bootstrapGame(loader.Parent)
6
+
7
+ local serviceBag = require("ServiceBag").new()
8
+ serviceBag:GetService(require("SnackbarServiceClient"))
9
+ serviceBag:Init()
10
+ serviceBag:Start()
11
+
12
+ local snackbarServiceClient = serviceBag:GetService(require("SnackbarServiceClient"))
13
+
14
+ local LipsumUtils = require("LipsumUtils")
15
+
16
+ local function showSnackbar()
17
+ snackbarServiceClient:ShowSnackbar(LipsumUtils.sentence(5), {
18
+ CallToAction = {
19
+ Text = LipsumUtils.word();
20
+ OnClick = function()
21
+ print("Activated action")
22
+ end;
23
+ }
24
+ })
25
+ end
26
+
27
+ showSnackbar()
28
+
29
+ workspace:WaitForChild("Part").ProximityPrompt.Triggered:Connect(function()
30
+ showSnackbar()
31
+ end)
@@ -0,0 +1,12 @@
1
+ --[[
2
+ @class ServerMain
3
+ ]]
4
+ local ServerScriptService = game:GetService("ServerScriptService")
5
+
6
+ local loader = ServerScriptService:FindFirstChild("LoaderUtils", true).Parent
7
+ local require = require(loader).bootstrapGame(ServerScriptService.snackbar)
8
+
9
+ local serviceBag = require("ServiceBag").new()
10
+ serviceBag:GetService(require("SnackbarService"))
11
+ serviceBag:Init()
12
+ serviceBag:Start()
@@ -1,250 +0,0 @@
1
- --[=[
2
- Snackbar, but draggable
3
- @class DraggableSnackbar
4
- ]=]
5
-
6
- local require = require(script.Parent.loader).load(script)
7
-
8
- local UserInputService = game:GetService("UserInputService")
9
- local RunService = game:GetService("RunService")
10
- local Players = game:GetService("Players")
11
- local GuiService = game:GetService("GuiService")
12
-
13
- local Snackbar = require("Snackbar")
14
- local qGUI = require("qGUI")
15
-
16
- local DraggableSnackbar = setmetatable({}, Snackbar)
17
- DraggableSnackbar.ClassName = "DraggableSnackbar"
18
- DraggableSnackbar.__index = DraggableSnackbar
19
- DraggableSnackbar.Vertical = true
20
- DraggableSnackbar.DefaultFadeOut = "FadeOutDown"
21
- DraggableSnackbar.Duration = 3
22
-
23
- -- By default the Snackbar will close automatically if the user types outside or presses the esc key.
24
- DraggableSnackbar.AutoCloseDisabled = false
25
-
26
- -- Note that this will not show until :Show() is called
27
- -- @constructor
28
- -- @param [GCOnDismissal] If true, will destroy itself and GC after being dismissed. Defaults to true
29
- -- @param [Options] Table of optional values, adds call to actions, et cetera
30
- function DraggableSnackbar.new(Parent, Text, GCOnDismissal, Options)
31
- local self = setmetatable(Snackbar.new(Parent, Text, Options), DraggableSnackbar)
32
-
33
- self._visible = false
34
- self._draggingCoroutine = nil
35
- self._shouldDismiss = false
36
- self._showId = 0
37
-
38
- self._mouse = Players.LocalPlayer:GetMouse()
39
- self._gcOnDismissal = GCOnDismissal == nil and true or false
40
-
41
- -- Set to transparency and faded out direction automatically
42
- self[self.DefaultFadeOut](self, true)
43
-
44
- return self
45
- end
46
-
47
- function DraggableSnackbar:Show()
48
- if not self._visible then
49
- self._visible = true
50
- self:FadeIn()
51
- local LocalShowId = self._showId + 1
52
- self._showId = LocalShowId
53
-
54
- -- Connect events
55
- self._whileActiveMaid:GiveTask(self.Gui.MouseButton1Down:Connect(function(X, Y)
56
- if self._showId == LocalShowId then
57
- if not self._draggingCoroutine then
58
- self:StartTrack(X, Y)
59
- end
60
- else
61
- warn("[DraggingBeginEvent] - self._showId ~= LocalShowId, but event fired")
62
- end
63
- end))
64
-
65
- self._whileActiveMaid:GiveTask(UserInputService.InputBegan:Connect(function(InputObject, GameProcessedEvent)
66
- if GameProcessedEvent then
67
- return
68
- end
69
-
70
- if self._showId ~= LocalShowId then
71
- warn("[InputDismissEvent] - self._showId ~= LocalShowId, but event fired")
72
- return
73
- end
74
- if self.AutoCloseDisabled then
75
- return
76
- end
77
-
78
- if qGUI.MouseOver(self._mouse, self.Gui) then
79
- return
80
- end
81
-
82
- if self.AbsolutePosition ~= self.Gui.AbsolutePosition then
83
- return -- Animating / dragging
84
- end
85
-
86
- if InputObject.UserInputType == Enum.UserInputType.Touch
87
- or InputObject.UserInputType == Enum.UserInputType.MouseButton1 then
88
-
89
- self:Dismiss()
90
- end
91
- end))
92
-
93
- -- Setup hide on dismissal
94
- task.delay(self.Duration, function()
95
- if self.Destroy and self._showId == LocalShowId and self._visible then
96
- self:Dismiss()
97
- end
98
- end)
99
- end
100
- end
101
-
102
- function DraggableSnackbar:StartTrack(X, Y)
103
- if self.Vertical then
104
- self._startDragPosition = Y
105
- else
106
- self._startDragPosition = X
107
- end
108
- self.DragOffset = 0
109
-
110
- local localDraggingCoroutine
111
- localDraggingCoroutine = coroutine.create(function()
112
- while self._draggingCoroutine == localDraggingCoroutine do
113
- self:Track()
114
- RunService.Stepped:Wait()
115
- end
116
- end)
117
- self._draggingCoroutine = localDraggingCoroutine
118
-
119
- self._whileActiveMaid.DraggingEnded = UserInputService.InputEnded:Connect(function(inputObject)
120
- if self._draggingCoroutine == localDraggingCoroutine then
121
- if inputObject.UserInputType.Name == "MouseButton1" then
122
- self:EndTrack()
123
- end
124
- else
125
- warn("[DraggableSnackbar] - InputEnded fire, but DraggingCoroutine was not the localDraggingCoroutine")
126
- end
127
- end)
128
-
129
- self._whileActiveMaid.TouchDraggingEnded = UserInputService.TouchEnded:Connect(function(_)
130
- if self._draggingCoroutine == localDraggingCoroutine then
131
- self:EndTrack()
132
- else
133
- warn("[DraggableSnackbar] - TouchEnded fire, but DraggingCoroutine was not the localDraggingCoroutine")
134
- end
135
- end)
136
-
137
- assert(coroutine.resume(self._draggingCoroutine))
138
- end
139
-
140
- function DraggableSnackbar:Track()
141
- local DragOffset, DragLength
142
- local TopLeftInset, _ = GuiService:GetGuiInset()
143
-
144
- if self.Vertical then
145
- DragOffset = (self._mouse.Y + TopLeftInset.Y) - self._startDragPosition
146
- DragLength = self.Gui.AbsoluteSize.Y
147
-
148
- self.Gui.Position = self.Position + UDim2.new(0, 0, 0, DragOffset)
149
- else
150
- DragOffset = (self._mouse.X + TopLeftInset.X) - self._startDragPosition
151
- DragLength = self.Gui.AbsoluteSize.Y
152
-
153
- self.Gui.Position = self.Position + UDim2.new(0, DragOffset, 0, 0)
154
- end
155
-
156
- local PercentFaded = math.abs(DragOffset) / DragLength
157
- if PercentFaded > 1 then
158
- PercentFaded = 1
159
- elseif PercentFaded < 0 then
160
- PercentFaded = 0
161
- end
162
-
163
- self:FadeOutTransparency(PercentFaded)
164
- end
165
-
166
- function DraggableSnackbar:GetOffsetXY()
167
- local Offset = self.Gui.AbsolutePosition - self.AbsolutePosition
168
- return Offset
169
- end
170
-
171
- function DraggableSnackbar:EndTrack()
172
- self._startDragPosition = nil
173
- self._draggingCoroutine = nil
174
-
175
- -- Cleanup events
176
- self._whileActiveMaid.DraggingEnded = nil
177
- self._whileActiveMaid.TouchDraggingEnded = nil
178
-
179
- -- Dismissal if dragged out
180
- if self._shouldDismiss then
181
- self:Dismiss()
182
- else
183
- local OffsetXY = self:GetOffsetXY()
184
- local SizeXY = self.Gui.AbsoluteSize
185
-
186
- if math.abs(OffsetXY.X) >= SizeXY.X or math.abs(OffsetXY.Y) >= SizeXY.Y then
187
- self:Dismiss()
188
- else
189
- self:FadeIn()
190
- end
191
- end
192
- end
193
-
194
- function DraggableSnackbar:Dismiss()
195
- if self._visible then
196
- if self._draggingCoroutine then
197
- self._shouldDismiss = true
198
- else
199
- self._visible = false
200
- self._shouldDismiss = nil
201
- self._whileActiveMaid:DoCleaning()
202
-
203
- local OffsetXY = self:GetOffsetXY()
204
- -- Determine what direction to fade out...
205
- if OffsetXY.X > 0 then
206
- self:FadeOutRight()
207
- elseif OffsetXY.X < 0 then
208
- self:FadeOutLeft()
209
- elseif OffsetXY.Y > 0 then
210
- self:FadeOutUp()
211
- elseif OffsetXY.Y < 0 then
212
- self:FadeOutDown()
213
- else
214
- self[self.DefaultFadeOut](self)
215
- end
216
-
217
- -- GC stuff
218
- if self._gcOnDismissal then
219
- self._gcOnDismissal = false -- Make sure this is only called once...
220
- delay(self.FadeTime, function()
221
- self:Destroy()
222
- end)
223
- end
224
- end
225
- else
226
- warn("[DraggableSnackbar] - Cannot dismiss, already hidden")
227
- end
228
- end
229
-
230
- function DraggableSnackbar:IsVisible()
231
- return self._visible
232
- end
233
-
234
- function DraggableSnackbar:Destroy()
235
- self.Gui:Destroy()
236
- self.Gui = nil
237
-
238
- self.TextLabel:Destroy()
239
- self.TextLabel = nil
240
-
241
- self._whileActiveMaid:DoCleaning()
242
- self._whileActiveMaid = nil
243
-
244
- self._visible = false
245
- self._draggingCoroutine = nil
246
-
247
- setmetatable(self, nil)
248
- end
249
-
250
- return DraggableSnackbar
@@ -1,292 +0,0 @@
1
- --[=[
2
- Snackbars provide lightweight feedback on an operation
3
- at the base of the screen. They automatically disappear
4
- after a timeout or user interaction. There can only be
5
- one on the screen at a time.
6
- @class Snackbar
7
- ]=]
8
-
9
- local require = require(script.Parent.loader).load(script)
10
-
11
- local qGUI = require("qGUI")
12
- local Maid = require("Maid")
13
- local Math = require("Math")
14
-
15
- -- Base clase, not functional
16
- local Snackbar = {}
17
- Snackbar.ClassName = "Snackbar"
18
- Snackbar.__index = Snackbar
19
- Snackbar.Height = 48
20
- Snackbar.MinimumWidth = 288 -- Taken from google material design
21
- Snackbar.MaximumWidth = 700
22
- Snackbar.TextWidthOffset = 24
23
- Snackbar.Position = UDim2.new(1, -10, 1, -10 - Snackbar.Height)
24
- Snackbar.FadeTime = 0.16
25
- Snackbar.CornerRadius = 2--24
26
-
27
- local DEFAULT_TEXT_COLOR = Color3.fromRGB(78, 205, 196)
28
-
29
- function Snackbar.new(Parent, Text, options)
30
- local self = setmetatable({}, Snackbar)
31
-
32
- local Gui = Instance.new("ImageButton")
33
- Gui.ZIndex = 7
34
- Gui.Name = "Snackbar"
35
- Gui.Size = UDim2.new(0, 100, 0, self.Height)
36
- Gui.BorderSizePixel = 0
37
- Gui.BackgroundColor3 = Color3.new(0.196, 0.196, 0.196) -- Google design specifications
38
- Gui.Archivable = false
39
- Gui.ClipsDescendants = false
40
- Gui.Position = self.Position
41
- Gui.AutoButtonColor = false
42
- Gui.BackgroundTransparency = 1
43
- self.Gui = Gui
44
-
45
- self.BackgroundImages = {qGUI.BackWithRoundedRectangle(Gui, self.CornerRadius, Gui.BackgroundColor3)}
46
-
47
- local ShadowRadius = 1
48
- local ShadowContainer = Instance.new("Frame")
49
- ShadowContainer.AnchorPoint = Vector2.new(0.5, 0.5)
50
- ShadowContainer.Parent = Gui
51
- ShadowContainer.Name = "ShadowContainer"
52
- ShadowContainer.BackgroundTransparency = 1
53
- ShadowContainer.Size = UDim2.new(1, ShadowRadius*2, 1, ShadowRadius*2)
54
- ShadowContainer.Archivable = false
55
- ShadowContainer.Position = UDim2.new(0.5, 0, 0.5, 0)
56
-
57
- -- Image is blurred at
58
- self.ShadowImages = {
59
- qGUI.AddNinePatch(ShadowContainer, "rbxassetid://191838004",
60
- Vector2.new(150, 150),
61
- self.CornerRadius + ShadowRadius,
62
- "ImageLabel"
63
- )
64
- }
65
-
66
- for _, item in pairs(self.ShadowImages) do
67
- item.ImageTransparency = 0.74
68
- item.ZIndex = Gui.ZIndex - 2
69
- end
70
-
71
- for _, item in pairs(self.BackgroundImages) do
72
- item.ZIndex = Gui.ZIndex - 1
73
- end
74
-
75
- local textLabel = Instance.new("TextLabel")
76
- textLabel.Size = UDim2.new(1, -self.TextWidthOffset*2, 0, 16)
77
- textLabel.Position = UDim2.new(0, self.TextWidthOffset, 0, 16)
78
- textLabel.TextXAlignment = Enum.TextXAlignment.Left
79
- textLabel.TextYAlignment = Enum.TextYAlignment.Center
80
- textLabel.Name = "SnackbarLabel"
81
- textLabel.TextTransparency = 0.87
82
- textLabel.TextColor3 = Color3.new(1, 1, 1)
83
- textLabel.BackgroundTransparency = 1
84
- textLabel.BorderSizePixel = 0
85
- textLabel.Font = Enum.Font.SourceSans
86
- textLabel.Text = Text
87
- textLabel.FontSize = Enum.FontSize.Size18
88
- textLabel.ZIndex = Gui.ZIndex-1
89
- textLabel.Parent = Gui
90
- self._textLabel = textLabel
91
-
92
- self._whileActiveMaid = Maid.new()
93
- self.Gui.Parent = Parent
94
-
95
- local callToActionText
96
- if options and options.CallToAction then
97
- if type(options.CallToAction) == "string" then
98
- callToActionText = options.CallToAction
99
- else
100
- callToActionText = tostring(options.CallToAction.Text)
101
- end
102
- callToActionText = callToActionText:upper()
103
-
104
- local button = Instance.new("TextButton")
105
- button.Name = "CallToActionButton"
106
- button.AnchorPoint = Vector2.new(1, 0.5)
107
- button.BackgroundTransparency = 1
108
- button.Position = UDim2.new(1, -self.TextWidthOffset, 0.5, 0)
109
- button.Size = UDim2.new(0.5, 0, 0.8, 0)
110
- button.Text = callToActionText
111
- button.Font = Enum.Font.SourceSans
112
- button.FontSize = textLabel.FontSize
113
- button.TextXAlignment = Enum.TextXAlignment.Right
114
- button.TextColor3 = DEFAULT_TEXT_COLOR
115
- button.ZIndex = Gui.ZIndex
116
- button.Parent = Gui
117
-
118
- -- Resize
119
- button.Size = UDim2.new(UDim.new(0, button.TextBounds.X), button.Size.Y)
120
-
121
- self._whileActiveMaid:GiveTask(button.MouseButton1Click:Connect(function()
122
- if options.CallToAction.OnClick then
123
- self:Dismiss()
124
- options.CallToAction.OnClick()
125
- end
126
- end))
127
-
128
- self._whileActiveMaid:GiveTask(button.MouseEnter:Connect(function()
129
- button.TextColor3 = DEFAULT_TEXT_COLOR:lerp(Color3.new(0, 0, 0), 0.2)
130
- end))
131
-
132
- self._whileActiveMaid:GiveTask(button.MouseLeave:Connect(function()
133
- button.TextColor3 = DEFAULT_TEXT_COLOR
134
- end))
135
-
136
- self._callToActionButton = button
137
- end
138
-
139
-
140
- local width = self._textLabel.TextBounds.X + self.TextWidthOffset*2
141
- if self._callToActionButton then
142
- width = width + self._callToActionButton.Size.X.Offset + self.TextWidthOffset*2
143
- end
144
-
145
- if width < self.MinimumWidth then
146
- width = self.MinimumWidth
147
- elseif width > self.MaximumWidth then
148
- width = self.MaximumWidth
149
- end
150
-
151
- if callToActionText then
152
- self._textLabel.Text = Text
153
- end
154
-
155
- self.Gui.Size = UDim2.new(0, width, 0, self.Height)
156
-
157
- self.Position = self.Position + UDim2.new(0, -width, 0, 0)
158
- self.Gui.Position = self.Position
159
- self.AbsolutePosition = self.Gui.AbsolutePosition
160
-
161
- return self
162
- end
163
-
164
- function Snackbar:Dismiss()
165
- error("Not implemented")
166
- end
167
-
168
- function Snackbar:SetBackgroundTransparency(Transparency)
169
- for _, item in pairs(self.BackgroundImages) do
170
- item.ImageTransparency = Transparency
171
- end
172
- for _, item in pairs(self.ShadowImages) do
173
- item.ImageTransparency = Math.map(Transparency, 0, 1, 0.74, 1)
174
- end
175
- end
176
-
177
- function Snackbar:FadeOutTransparency(PercentFaded)
178
- if PercentFaded then
179
- self:SetBackgroundTransparency(Math.map(PercentFaded, 0, 1, 0, 1))
180
- self._textLabel.TextTransparency = Math.map(PercentFaded, 0, 1, 0.13, 1)
181
-
182
- if self._callToActionButton then
183
- self._callToActionButton.TextTransparency = PercentFaded
184
- end
185
- else
186
- local newProperties = {
187
- ImageTransparency = 1;
188
- }
189
-
190
- for _, item in pairs(self.BackgroundImages) do
191
- qGUI.TweenTransparency(item, newProperties, self.FadeTime, true)
192
- end
193
- for _, item in pairs(self.ShadowImages) do
194
- qGUI.TweenTransparency(item, newProperties, self.FadeTime, true)
195
- end
196
-
197
- qGUI.TweenTransparency(self._textLabel, {
198
- TextTransparency = 1;
199
- }, self.FadeTime, true)
200
-
201
- if self._callToActionButton then
202
- qGUI.TweenTransparency(self._callToActionButton, {
203
- TextTransparency = 1;
204
- }, self.FadeTime, true)
205
- end
206
- end
207
- end
208
-
209
- -- Will animate unless given PercentFaded
210
- function Snackbar:FadeInTransparency(PercentFaded)
211
- if PercentFaded then
212
- -- self.Gui.BackgroundTransparency = Math.map(PercentFaded, 0, 1, 1, 0)
213
- self:SetBackgroundTransparency(Math.map(PercentFaded, 0, 1, 1, 0))
214
- self._textLabel.TextTransparency = Math.map(PercentFaded, 0, 1, 1, 0.13)
215
-
216
- if self._callToActionButton then
217
- self._callToActionButton.TextTransparency = PercentFaded
218
- end
219
- else
220
- -- Should be an ease-in-out transparency fade.
221
- do
222
- local newProperties = {
223
- ImageTransparency = 0;
224
- }
225
- for _, item in pairs(self.BackgroundImages) do
226
- qGUI.TweenTransparency(item, newProperties, self.FadeTime, true)
227
- end
228
- end
229
-
230
- do
231
- local newProperties = {
232
- ImageTransparency = 0.74;
233
- }
234
- for _, item in pairs(self.ShadowImages) do
235
- qGUI.TweenTransparency(item, newProperties, self.FadeTime, true)
236
- end
237
- end
238
-
239
- qGUI.TweenTransparency(self._textLabel, {
240
- TextTransparency = 0.13;
241
- }, self.FadeTime, true)
242
-
243
- if self._callToActionButton then
244
- qGUI.TweenTransparency(self._callToActionButton, {
245
- TextTransparency = 0;
246
- }, self.FadeTime, true)
247
- end
248
- end
249
- end
250
-
251
- -- Utility function
252
- function Snackbar:FadeHandler(NewPosition, DoNotAnimate, IsFadingOut)
253
- assert(NewPosition, "[Snackbar] - Internal function should not have been called. Missing NewPosition")
254
-
255
- if IsFadingOut then
256
- self:FadeOutTransparency(DoNotAnimate and 1 or nil)
257
- else
258
- self:FadeInTransparency(DoNotAnimate and 1 or nil)
259
- end
260
-
261
- if DoNotAnimate then
262
- self.Gui.Position = NewPosition
263
- else
264
- self.Gui:TweenPosition(NewPosition, "InOut", "Quad", self.FadeTime, true)
265
- end
266
- end
267
-
268
- function Snackbar:FadeOutUp(DoNotAnimate)
269
- local NewPosition = self.Position + UDim2.new(0, 0, 0, -self.Gui.AbsoluteSize.Y)
270
- self:FadeHandler(NewPosition, DoNotAnimate, true)
271
- end
272
-
273
- function Snackbar:FadeOutDown(DoNotAnimate)
274
- local NewPosition = self.Position + UDim2.new(0, 0, 0, self.Gui.AbsoluteSize.Y)
275
- self:FadeHandler(NewPosition, DoNotAnimate, true)
276
- end
277
-
278
- function Snackbar:FadeOutRight(DoNotAnimate)
279
- local NewPosition = self.Position + UDim2.new(0, self.Gui.AbsoluteSize.X, 0, 0)
280
- self:FadeHandler(NewPosition, DoNotAnimate, true)
281
- end
282
-
283
- function Snackbar:FadeOutLeft(DoNotAnimate)
284
- local NewPosition = self.Position + UDim2.new(0, -self.Gui.AbsoluteSize.X, 0, 0)
285
- self:FadeHandler(NewPosition, DoNotAnimate, true)
286
- end
287
-
288
- function Snackbar:FadeIn(DoNotAnimate)
289
- self:FadeHandler(self.Position, DoNotAnimate, false)
290
- end
291
-
292
- return Snackbar