Create Github Service
This commit is contained in:
parent
049ea7c4e6
commit
663e820d26
2 changed files with 187 additions and 111 deletions
|
|
@ -10,39 +10,13 @@ import qs.Widgets
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string latestVersion: "Unknown"
|
property string latestVersion: Github.latestVersion
|
||||||
property string currentVersion: "v1.2.1" // Fallback version
|
property string currentVersion: "v1.2.1" // Fallback version
|
||||||
property var contributors: []
|
property var contributors: Github.contributors
|
||||||
property string githubDataPath: Settings.configDir + "github_data.json"
|
|
||||||
|
|
||||||
function loadFromFile() {
|
Component.onCompleted: {
|
||||||
const now = Date.now();
|
// Initialize the Github service
|
||||||
const data = githubData;
|
Github.init();
|
||||||
if (!data.timestamp || (now - data.timestamp > 3.6e+06)) {
|
|
||||||
console.log("[About] Cache expired or missing, fetching new data from GitHub...");
|
|
||||||
fetchFromGitHub();
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
console.log("[About] Loading cached GitHub data (age: " + Math.round((now - data.timestamp) / 60000) + " minutes)");
|
|
||||||
if (data.version)
|
|
||||||
root.latestVersion = data.version;
|
|
||||||
|
|
||||||
if (data.contributors) {
|
|
||||||
root.contributors = data.contributors;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function fetchFromGitHub() {
|
|
||||||
versionProcess.running = true;
|
|
||||||
contributorsProcess.running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveData() {
|
|
||||||
githubData.timestamp = Date.now();
|
|
||||||
Qt.callLater(() => {
|
|
||||||
githubDataFile.writeAdapter();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
@ -71,86 +45,6 @@ ColumnLayout {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileView {
|
|
||||||
id: githubDataFile
|
|
||||||
|
|
||||||
path: root.githubDataPath
|
|
||||||
blockLoading: true
|
|
||||||
printErrors: true
|
|
||||||
watchChanges: true
|
|
||||||
onFileChanged: githubDataFile.reload()
|
|
||||||
onLoaded: loadFromFile()
|
|
||||||
onLoadFailed: function(error) {
|
|
||||||
console.log("GitHub data file doesn't exist yet, creating it...");
|
|
||||||
githubData.version = "Unknown";
|
|
||||||
githubData.contributors = [];
|
|
||||||
githubData.timestamp = 0;
|
|
||||||
githubDataFile.writeAdapter();
|
|
||||||
fetchFromGitHub();
|
|
||||||
}
|
|
||||||
Component.onCompleted: {
|
|
||||||
if (path)
|
|
||||||
reload();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonAdapter {
|
|
||||||
id: githubData
|
|
||||||
|
|
||||||
property string version: "Unknown"
|
|
||||||
property var contributors: []
|
|
||||||
property double timestamp: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: versionProcess
|
|
||||||
|
|
||||||
command: ["curl", "-s", "https://api.github.com/repos/Ly-sec/Noctalia/releases/latest"]
|
|
||||||
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
try {
|
|
||||||
const data = JSON.parse(text);
|
|
||||||
if (data.tag_name) {
|
|
||||||
const version = data.tag_name;
|
|
||||||
githubData.version = version;
|
|
||||||
root.latestVersion = version;
|
|
||||||
console.log("[About] Latest version fetched from GitHub:", version);
|
|
||||||
} else {
|
|
||||||
console.log("No tag_name in GitHub response");
|
|
||||||
}
|
|
||||||
saveData();
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to parse version:", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: contributorsProcess
|
|
||||||
|
|
||||||
command: ["curl", "-s", "https://api.github.com/repos/Ly-sec/Noctalia/contributors?per_page=100"]
|
|
||||||
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
try {
|
|
||||||
const data = JSON.parse(text);
|
|
||||||
githubData.contributors = data || [];
|
|
||||||
root.contributors = githubData.contributors;
|
|
||||||
saveData();
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to parse contributors:", e);
|
|
||||||
root.contributors = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrollView {
|
ScrollView {
|
||||||
id: scrollView
|
id: scrollView
|
||||||
|
|
||||||
|
|
|
||||||
182
Services/Github.qml
Normal file
182
Services/Github.qml
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import qs.Services
|
||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
// GitHub API logic and caching
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property string githubDataFile: Quickshell.env("NOCTALIA_GITHUB_FILE") || (Settings.cacheDir + "github.json")
|
||||||
|
property int githubUpdateFrequency: 60 * 60 // 1 hour expressed in seconds
|
||||||
|
property var data: adapter // Used to access via Github.data.xxx.yyy
|
||||||
|
property bool isFetchingData: false
|
||||||
|
|
||||||
|
// Public properties for easy access
|
||||||
|
property string latestVersion: "Unknown"
|
||||||
|
property var contributors: []
|
||||||
|
|
||||||
|
FileView {
|
||||||
|
objectName: "githubDataFileView"
|
||||||
|
path: githubDataFile
|
||||||
|
watchChanges: true
|
||||||
|
onFileChanged: reload()
|
||||||
|
onAdapterUpdated: writeAdapter()
|
||||||
|
Component.onCompleted: function () {
|
||||||
|
reload()
|
||||||
|
}
|
||||||
|
onLoaded: function () {
|
||||||
|
loadFromCache()
|
||||||
|
}
|
||||||
|
onLoadFailed: function (error) {
|
||||||
|
if (error.toString().includes("No such file") || error === 2) {
|
||||||
|
// File doesn't exist, create it with default values
|
||||||
|
console.log("[Github] Creating new cache file...");
|
||||||
|
writeAdapter()
|
||||||
|
// Fetch data after a short delay to ensure file is created
|
||||||
|
Qt.callLater(() => {
|
||||||
|
fetchFromGitHub()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonAdapter {
|
||||||
|
id: adapter
|
||||||
|
|
||||||
|
property string version: "Unknown"
|
||||||
|
property var contributors: []
|
||||||
|
property double timestamp: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
function init() {
|
||||||
|
// does nothing but ensure the singleton is created
|
||||||
|
// do not remove
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
function loadFromCache() {
|
||||||
|
const now = Date.now();
|
||||||
|
if (!data.timestamp || (now - data.timestamp > githubUpdateFrequency * 1000)) {
|
||||||
|
console.log("[Github] Cache expired or missing, fetching new data from GitHub...");
|
||||||
|
fetchFromGitHub();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("[Github] Loading cached GitHub data (age: " + Math.round((now - data.timestamp) / 60000) + " minutes)");
|
||||||
|
|
||||||
|
if (data.version) {
|
||||||
|
root.latestVersion = data.version;
|
||||||
|
}
|
||||||
|
if (data.contributors) {
|
||||||
|
root.contributors = data.contributors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
function fetchFromGitHub() {
|
||||||
|
if (isFetchingData) {
|
||||||
|
console.warn("[Github] GitHub data is still fetching")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isFetchingData = true
|
||||||
|
versionProcess.running = true;
|
||||||
|
contributorsProcess.running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
function saveData() {
|
||||||
|
data.timestamp = Date.now();
|
||||||
|
Qt.callLater(() => {
|
||||||
|
// Access the FileView's writeAdapter method
|
||||||
|
var fileView = root.children.find(child => child.objectName === "githubDataFileView");
|
||||||
|
if (fileView) {
|
||||||
|
fileView.writeAdapter();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
function resetCache() {
|
||||||
|
data.version = "Unknown"
|
||||||
|
data.contributors = []
|
||||||
|
data.timestamp = 0
|
||||||
|
|
||||||
|
// Try to fetch immediately
|
||||||
|
fetchFromGitHub()
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: versionProcess
|
||||||
|
|
||||||
|
command: ["curl", "-s", "https://api.github.com/repos/Ly-sec/Noctalia/releases/latest"]
|
||||||
|
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
try {
|
||||||
|
const response = text;
|
||||||
|
if (response && response.trim()) {
|
||||||
|
const data = JSON.parse(response);
|
||||||
|
if (data.tag_name) {
|
||||||
|
const version = data.tag_name;
|
||||||
|
root.data.version = version;
|
||||||
|
root.latestVersion = version;
|
||||||
|
console.log("[Github] Latest version fetched from GitHub:", version);
|
||||||
|
} else {
|
||||||
|
console.log("[Github] No tag_name in GitHub response");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log("[Github] Empty response from GitHub API");
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[Github] Failed to parse version:", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if both processes are done
|
||||||
|
checkAndSaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: contributorsProcess
|
||||||
|
|
||||||
|
command: ["curl", "-s", "https://api.github.com/repos/Ly-sec/Noctalia/contributors?per_page=100"]
|
||||||
|
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
try {
|
||||||
|
const response = text;
|
||||||
|
if (response && response.trim()) {
|
||||||
|
const data = JSON.parse(response);
|
||||||
|
root.data.contributors = data || [];
|
||||||
|
root.contributors = root.data.contributors;
|
||||||
|
console.log("[Github] Contributors fetched from GitHub:", root.contributors.length);
|
||||||
|
} else {
|
||||||
|
console.log("[Github] Empty response from GitHub API for contributors");
|
||||||
|
root.data.contributors = [];
|
||||||
|
root.contributors = [];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("[Github] Failed to parse contributors:", e);
|
||||||
|
root.data.contributors = [];
|
||||||
|
root.contributors = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if both processes are done
|
||||||
|
checkAndSaveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
function checkAndSaveData() {
|
||||||
|
// Only save when both processes are finished
|
||||||
|
if (!versionProcess.running && !contributorsProcess.running) {
|
||||||
|
root.isFetchingData = false;
|
||||||
|
root.saveData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue