Skip to content

Commit

Permalink
feat: duplicate widget
Browse files Browse the repository at this point in the history
  • Loading branch information
sametcn99 committed Jun 11, 2024
1 parent 1b61725 commit 7026ace
Show file tree
Hide file tree
Showing 14 changed files with 64 additions and 30 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "electron-widgets",
"productName": "electron-widgets",
"version": "2.1.2",
"version": "2.1.3",
"description": "A minimal widget application created with electron.js",
"license": "GPL-3.0",
"repository": {
Expand Down
5 changes: 3 additions & 2 deletions public/widgets/app releases/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
Expand All @@ -21,7 +21,8 @@ <h1 id="header">
width="24px"
height="24px"
/>
Releases
Releases<br />
<span id="version">Using version</span>
</h1>
<section id="container">
<article id="item">
Expand Down
7 changes: 7 additions & 0 deletions public/widgets/app releases/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ async function fetchDataAndUpdateUI() {
});
}

// Check for app updates
const version = await window.electronAPI.getAppVersion();

// Update the UI with the app version
document.getElementById("version").textContent =
`You are using version ${version} of the app.`;

// Update the UI if data is available
if (data) updateUI();

Expand Down
9 changes: 2 additions & 7 deletions public/widgets/hacker news/styles.css
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
/* Importing Google Fonts */
@import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap");

/* Custom font face */
@font-face {
font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
src: url();
}

* {
margin: 0;
padding: 0;
user-select: none;
-webkit-user-select: none;
font-family: "Roboto", sans-serif;
}

:root {
Expand Down Expand Up @@ -63,7 +58,7 @@ body {

#time {
font-size: small;
font-weight: lighter;
font-weight: 600;
}

#footer {
Expand Down
1 change: 1 addition & 0 deletions public/widgets/r-programming/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ <h1 id="header">
<section id="container">
<article id="item">
<div id="title">title goes here</div>
<p id="detail"></p>
<div>
<p id="pubDate">Published on: May 1, 2024</p>
<div id="author" rel="noopener noreferrer">
Expand Down
8 changes: 6 additions & 2 deletions public/widgets/r-programming/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ async function fetchDataAndUpdateUI() {
node.style.display = "flex";
// Set the title of the item
node.querySelector("#title").textContent = element.title;
if(element.message) {
node.querySelector("#detail").textContent = element.message.substring(0, 250) + "...";
node.querySelector("#detail").style.display = "block";
}
// Add an event listener to open the link when the title is clicked
node.querySelector("#title").addEventListener("click", () => {
window.electronAPI.openExternal(element.link);
Expand All @@ -40,7 +44,7 @@ async function fetchDataAndUpdateUI() {

// Fetch the RSS feed data
const data = await fetch(
"https://reddit-rss-api.deno.dev/r/programming?sort=desc",
"https://reddit-rss-api.deno.dev/r/programming?sort=desc"
).then((response) => response.json());
// Log the data
console.log(data);
Expand All @@ -49,7 +53,7 @@ async function fetchDataAndUpdateUI() {
// Set an interval to reload the widget every hour
setInterval(
() => window.electronAPI.reloadWidget("r-turkey"),
1000 * 60 * 60, // reload every hour
1000 * 60 * 60 // reload every hour
);
}

Expand Down
9 changes: 1 addition & 8 deletions public/widgets/r-programming/styles.css
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
/* Importing Google Fonts */
@import url("https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap");

/* Custom font face */
@font-face {
font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
src: url();
}

/* Global CSS styles */
* {
padding: 0px;
Expand Down Expand Up @@ -61,11 +55,10 @@ h1 {
color: var(--text);
position: sticky;
top: 0;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
width: 100%;
padding-top: 10px;
padding-bottom: 10px;
background-color: var(--background);
}

/* Anchor styles */
Expand Down
24 changes: 24 additions & 0 deletions src/app/main/ipc-operations/widget-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,27 @@ ipcMain.handle(IpcChannels.REMOVE_WIDGET, async (event, widgetKey) => {
setWidgetsJson(widgets, config.widgetsJsonPath);
windowManager.reloadAllWindows();
});

/**
* Handles duplicating a widget.
* @param event - The event object.
* @param widgetKey - The key of the widget to duplicate.
*/
ipcMain.handle(IpcChannels.DUPLICATE_WIDGET, async (event, widgetKey) => {
const widgets = getWidgetsJson(config.widgetsJsonPath);
const widget = widgets[widgetKey];
const widgetFolderPath = path.join(config.widgetsDir, widgetKey);
const randomNumber = Math.floor(Math.random() * 1000);
const newWidgetId = `${widgetKey}-${randomNumber}`;
const newWidgetFolderPath = path.join(config.widgetsDir, newWidgetId);
copySync(widgetFolderPath, newWidgetFolderPath);
widgets[newWidgetId] = { ...widget };
widgets[newWidgetId].title = newWidgetId
widgets[newWidgetId].visible = false;
widgets[newWidgetId].x = 10;
widgets[newWidgetId].y = 10;
widgets[newWidgetId].locked = false;
widgets[newWidgetId].alwaysOnTop = false;
setWidgetsJson(widgets, config.widgetsJsonPath);
windowManager.reloadAllWindows();
});
2 changes: 2 additions & 0 deletions src/app/preload/electronAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ contextBridge.exposeInMainWorld("electronAPI", {
removeWidget: (widgetId: string) =>
ipcRenderer.invoke(IpcChannels.REMOVE_WIDGET, widgetId),
sortWidgets: () => ipcRenderer.invoke(IpcChannels.SORT_WIDGETS),
duplicateWidget: (widgetId: string) =>
ipcRenderer.invoke(IpcChannels.DUPLICATE_WIDGET, widgetId),

// widget window operations
createWidgetWindow: (widgetKey: string) =>
Expand Down
5 changes: 5 additions & 0 deletions src/app/renderer/components/DropdownButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<div class="relative" v-on:mouseover="isOpen = true" v-on:mouseleave="isOpen = false">
<Bars4Icon class="w-6 h-6 rounded-xl hover:scale-105 hover:cursor-pointer" />
<div v-if="isOpen" class="absolute right-0 z-10 py-2 text-sm bg-gray-300 rounded-lg shadow-xl w-36">
<button class="w-full p-2 text-gray-900 hover:bg-red-800 hover:text-white"
@click="duplicateWidget()">Duplicate</button>
<button v-if="visible === true" class="w-full p-2 text-gray-900 hover:bg-gray-900 hover:text-white"
@click="show()">Show</button>
<button v-if="alwaysOnTop === true" class="w-full p-2 text-gray-900 hover:bg-gray-900 hover:text-white"
Expand Down Expand Up @@ -32,6 +34,9 @@ export default {
},
show() {
window.electronAPI.showWidget(this.title || '');
},
duplicateWidget() {
window.electronAPI.duplicateWidget(this.title || '');
}
},
props: {
Expand Down
1 change: 1 addition & 0 deletions src/lib/ipc-channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export enum IpcChannels {

SHOW_WIDGET = "show-widget", // Channel for showing widgets
SHOW_ALL_WIDGETS = "show-all-widgets", // Channel for showing all widgets
DUPLICATE_WIDGET = "duplicate-widget", // Channel for duplicating widgets
RELOAD_WIDGET = "reload-widget", // Channel for refreshing widgets
RECREATE_WIDGET = "recreate-widget", // Channel for recreating widgets
RESIZE_WIDGET_WINDOW = "resize-widget-window", // Channel for resizing widget windows
Expand Down
1 change: 1 addition & 0 deletions src/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ interface Window {
// Widget actions
reloadWidget: (widgetKey: string) => Promise<void>;
recreateWidget: (widgetKey: string) => Promise<void>;
duplicateWidget: (widgetKey: string) => Promise<void>;
lockWidget: (widgetId: string) => Promise<void>;
getLocation: () => Promise<void>;
showNotification: (title: string, body?: string) => Promise<void>;
Expand Down
16 changes: 8 additions & 8 deletions src/utils/browser-windows/window-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class WindowManager {
try {
let mainWindow: Electron.BrowserWindow | undefined;
BrowserWindow.getAllWindows().forEach((win) => {
if (win.webContents.getTitle() === config.applicationName) {
if (win.title === config.applicationName) {
mainWindow = win;
}
});
Expand All @@ -25,7 +25,7 @@ class WindowManager {
minimizeAllWindowsExceptMain(): void {
try {
BrowserWindow.getAllWindows().forEach((win) => {
if (win.webContents.getTitle() !== config.applicationName) {
if (win.title !== config.applicationName) {
win.minimize();
}
});
Expand All @@ -38,7 +38,7 @@ class WindowManager {
closeAllWindowsExceptMain(): void {
try {
BrowserWindow.getAllWindows().forEach((win) => {
if (win.webContents.getTitle() !== config.applicationName) {
if (win.title !== config.applicationName) {
win.close();
}
});
Expand All @@ -65,7 +65,7 @@ class WindowManager {

reCreateWidget(widgetKey: string): void {
this.getAllWindowsExceptMain().forEach((win) => {
if (win.webContents.getTitle() === widgetKey) {
if (win.title === widgetKey) {
win.close();
createSingleWindowForWidgets(widgetKey);
}
Expand All @@ -81,7 +81,7 @@ class WindowManager {

reloadWidget(widgetKey: string): void {
this.getAllWindowsExceptMain().forEach((win) => {
if (win.webContents.getTitle() === widgetKey) {
if (win.title === widgetKey) {
win.reload();
}
});
Expand Down Expand Up @@ -156,7 +156,7 @@ class WindowManager {
hideAllWindowsExceptMain(): void {
try {
BrowserWindow.getAllWindows().forEach((win) => {
if (win.webContents.getTitle() !== config.applicationName) {
if (win.title !== config.applicationName) {
win.hide();
}
});
Expand All @@ -169,7 +169,7 @@ class WindowManager {
setAlwaysOnTopAllWindowsExceptMain(alwaysOnTop: boolean): void {
try {
BrowserWindow.getAllWindows().forEach((win) => {
if (win.webContents.getTitle() !== config.applicationName) {
if (win.title!== config.applicationName) {
win.setAlwaysOnTop(alwaysOnTop);
}
});
Expand Down Expand Up @@ -209,7 +209,7 @@ class WindowManager {
try {
let foundWindow: BrowserWindow | null = null;
this.getAllWindowsExceptMain().forEach((win) => {
if (win.webContents.getTitle() === title) {
if (win.title=== title) {
foundWindow = win;
}
});
Expand Down

0 comments on commit 7026ace

Please sign in to comment.