mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-20 12:45:05 +00:00
Show update indicator on version header (#1069)
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
# Rojo Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
* Added an update indicator to the version header when a new version of the plugin is available. ([#1069])
|
||||
|
||||
[#1069]: https://github.com/rojo-rbx/rojo/pull/1069
|
||||
|
||||
## 7.5.1 - April 25th, 2025
|
||||
* Fixed output spam related to `Instance.Capabilities` in the plugin
|
||||
|
||||
|
||||
@@ -9,8 +9,70 @@ local Assets = require(Plugin.Assets)
|
||||
local Config = require(Plugin.Config)
|
||||
local Version = require(Plugin.Version)
|
||||
|
||||
local Tooltip = require(Plugin.App.Components.Tooltip)
|
||||
local SlicedImage = require(script.Parent.SlicedImage)
|
||||
|
||||
local e = Roact.createElement
|
||||
|
||||
local function VersionIndicator(props)
|
||||
local updateMessage = Version.getUpdateMessage()
|
||||
|
||||
return Theme.with(function(theme)
|
||||
return e("Frame", {
|
||||
LayoutOrder = props.layoutOrder,
|
||||
Size = UDim2.new(0, 0, 0, 25),
|
||||
BackgroundTransparency = 1,
|
||||
AutomaticSize = Enum.AutomaticSize.X,
|
||||
}, {
|
||||
Border = if updateMessage
|
||||
then e(SlicedImage, {
|
||||
slice = Assets.Slices.RoundedBorder,
|
||||
color = theme.Button.Bordered.Enabled.BorderColor,
|
||||
transparency = props.transparency,
|
||||
size = UDim2.fromScale(1, 1),
|
||||
zIndex = 0,
|
||||
}, {
|
||||
Indicator = e("ImageLabel", {
|
||||
Size = UDim2.new(0, 10, 0, 10),
|
||||
ScaleType = Enum.ScaleType.Fit,
|
||||
Image = Assets.Images.Circles[16],
|
||||
ImageColor3 = theme.Header.LogoColor,
|
||||
ImageTransparency = props.transparency,
|
||||
BackgroundTransparency = 1,
|
||||
Position = UDim2.new(1, 0, 0, 0),
|
||||
AnchorPoint = Vector2.new(0.5, 0.5),
|
||||
}),
|
||||
})
|
||||
else nil,
|
||||
|
||||
Tip = if updateMessage
|
||||
then e(Tooltip.Trigger, {
|
||||
text = updateMessage,
|
||||
delay = 0.1,
|
||||
})
|
||||
else nil,
|
||||
|
||||
VersionText = e("TextLabel", {
|
||||
Text = Version.display(Config.version),
|
||||
FontFace = theme.Font.Thin,
|
||||
TextSize = theme.TextSize.Body,
|
||||
TextColor3 = theme.Header.VersionColor,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
TextTransparency = props.transparency,
|
||||
BackgroundTransparency = 1,
|
||||
|
||||
Size = UDim2.new(0, 0, 1, 0),
|
||||
AutomaticSize = Enum.AutomaticSize.X,
|
||||
}, {
|
||||
Padding = e("UIPadding", {
|
||||
PaddingLeft = UDim.new(0, 6),
|
||||
PaddingRight = UDim.new(0, 6),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
local function Header(props)
|
||||
return Theme.with(function(theme)
|
||||
return e("Frame", {
|
||||
@@ -29,18 +91,9 @@ local function Header(props)
|
||||
BackgroundTransparency = 1,
|
||||
}),
|
||||
|
||||
Version = e("TextLabel", {
|
||||
Text = Version.display(Config.version),
|
||||
FontFace = theme.Font.Thin,
|
||||
TextSize = theme.TextSize.Body,
|
||||
TextColor3 = theme.Header.VersionColor,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
TextTransparency = props.transparency,
|
||||
|
||||
Size = UDim2.new(1, 0, 0, theme.TextSize.Body),
|
||||
|
||||
LayoutOrder = 2,
|
||||
BackgroundTransparency = 1,
|
||||
VersionIndicator = e(VersionIndicator, {
|
||||
transparency = props.transparency,
|
||||
layoutOrder = 2,
|
||||
}),
|
||||
|
||||
Layout = e("UIListLayout", {
|
||||
|
||||
@@ -216,7 +216,7 @@ function Trigger:managePopup()
|
||||
return
|
||||
end
|
||||
|
||||
self.showDelayThread = task.delay(DELAY, function()
|
||||
self.showDelayThread = task.delay(self.props.delay or DELAY, function()
|
||||
self.props.context.addTip(self.id, {
|
||||
Text = self.props.text,
|
||||
Position = self:getMousePos(),
|
||||
|
||||
@@ -251,27 +251,10 @@ function App:closeNotification(id: number)
|
||||
end
|
||||
|
||||
function App:checkForUpdates()
|
||||
if not Settings:get("checkForUpdates") then
|
||||
return
|
||||
end
|
||||
local updateMessage = Version.getUpdateMessage()
|
||||
|
||||
local isLocalInstall = string.find(debug.traceback(), "\n[^\n]-user_.-$") ~= nil
|
||||
local latestCompatibleVersion = Version.retrieveLatestCompatible({
|
||||
version = Config.version,
|
||||
includePrereleases = isLocalInstall and Settings:get("checkForPrereleases"),
|
||||
})
|
||||
if not latestCompatibleVersion then
|
||||
return
|
||||
end
|
||||
|
||||
self:addNotification(
|
||||
string.format(
|
||||
"A newer compatible version of Rojo, %s, was published %s! Go to the Rojo releases page to learn more.",
|
||||
Version.display(latestCompatibleVersion.version),
|
||||
timeUtil.elapsedToText(DateTime.now().UnixTimestamp - latestCompatibleVersion.publishedUnixTimestamp)
|
||||
),
|
||||
500,
|
||||
{
|
||||
if updateMessage then
|
||||
self:addNotification(updateMessage, 500, {
|
||||
Dismiss = {
|
||||
text = "Dismiss",
|
||||
style = "Bordered",
|
||||
@@ -280,8 +263,8 @@ function App:checkForUpdates()
|
||||
notification:dismiss()
|
||||
end,
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
function App:getPriorSyncInfo(): { host: string?, port: string?, projectName: string?, timestamp: number? }
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
local Packages = script.Parent.Parent.Packages
|
||||
local Rojo = script:FindFirstAncestor("Rojo")
|
||||
local Plugin = Rojo.Plugin
|
||||
local Packages = Rojo.Packages
|
||||
|
||||
local Http = require(Packages.Http)
|
||||
local Promise = require(Packages.Promise)
|
||||
local Log = require(Packages.Log)
|
||||
|
||||
local Config = require(Plugin.Config)
|
||||
local Settings = require(Plugin.Settings)
|
||||
local timeUtil = require(Plugin.timeUtil)
|
||||
|
||||
type LatestReleaseInfo = {
|
||||
version: { number },
|
||||
prerelease: boolean,
|
||||
publishedUnixTimestamp: number,
|
||||
}
|
||||
|
||||
local function compare(a, b)
|
||||
if a > b then
|
||||
@@ -88,14 +102,26 @@ function Version.display(version)
|
||||
return output
|
||||
end
|
||||
|
||||
--[[
|
||||
The GitHub API rate limit for unauthenticated requests is rather low,
|
||||
and we don't release often enough to warrant checking it more than once a day.
|
||||
--]]
|
||||
Version._cachedLatestCompatible = nil :: {
|
||||
value: LatestReleaseInfo?,
|
||||
timestamp: number,
|
||||
}?
|
||||
|
||||
function Version.retrieveLatestCompatible(options: {
|
||||
version: { number },
|
||||
includePrereleases: boolean?,
|
||||
}): {
|
||||
version: { number },
|
||||
prerelease: boolean,
|
||||
publishedUnixTimestamp: number,
|
||||
}?
|
||||
}): LatestReleaseInfo?
|
||||
if Version._cachedLatestCompatible and os.clock() - Version._cachedLatestCompatible.timestamp < 60 * 60 * 24 then
|
||||
Log.debug("Using cached latest compatible version")
|
||||
return Version._cachedLatestCompatible.value
|
||||
end
|
||||
|
||||
Log.debug("Retrieving latest compatible version from GitHub")
|
||||
|
||||
local success, releases = Http.get("https://api.github.com/repos/rojo-rbx/rojo/releases?per_page=10")
|
||||
:andThen(function(response)
|
||||
if response.code >= 400 then
|
||||
@@ -114,7 +140,7 @@ function Version.retrieveLatestCompatible(options: {
|
||||
end
|
||||
|
||||
-- Iterate through releases, looking for the latest compatible version
|
||||
local latestCompatible = nil
|
||||
local latestCompatible: LatestReleaseInfo? = nil
|
||||
for _, release in releases do
|
||||
-- Skip prereleases if they are not requested
|
||||
if (not options.includePrereleases) and release.prerelease then
|
||||
@@ -142,10 +168,43 @@ function Version.retrieveLatestCompatible(options: {
|
||||
|
||||
-- Don't return anything if the latest found is not newer than the current version
|
||||
if latestCompatible == nil or Version.compare(latestCompatible.version, options.version) <= 0 then
|
||||
-- Cache as nil so we don't try again for a day
|
||||
Version._cachedLatestCompatible = {
|
||||
value = nil,
|
||||
timestamp = os.clock(),
|
||||
}
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Cache the latest compatible version
|
||||
Version._cachedLatestCompatible = {
|
||||
value = latestCompatible,
|
||||
timestamp = os.clock(),
|
||||
}
|
||||
|
||||
return latestCompatible
|
||||
end
|
||||
|
||||
function Version.getUpdateMessage(): string?
|
||||
if not Settings:get("checkForUpdates") then
|
||||
return
|
||||
end
|
||||
|
||||
local isLocalInstall = string.find(debug.traceback(), "\n[^\n]-user_.-$") ~= nil
|
||||
local latestCompatibleVersion = Version.retrieveLatestCompatible({
|
||||
version = Config.version,
|
||||
includePrereleases = isLocalInstall and Settings:get("checkForPrereleases"),
|
||||
})
|
||||
if not latestCompatibleVersion then
|
||||
return
|
||||
end
|
||||
|
||||
return string.format(
|
||||
"A newer compatible version of Rojo, %s, was published %s! Go to the Rojo releases page to learn more.",
|
||||
Version.display(latestCompatibleVersion.version),
|
||||
timeUtil.elapsedToText(DateTime.now().UnixTimestamp - latestCompatibleVersion.publishedUnixTimestamp)
|
||||
)
|
||||
end
|
||||
|
||||
return Version
|
||||
|
||||
Reference in New Issue
Block a user