Skip to content

Commit

Permalink
[Workspaces] implement Launch on startup feature
Browse files Browse the repository at this point in the history
  • Loading branch information
donlaci committed Jan 8, 2025
1 parent a29ff07 commit a95d51b
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 15 deletions.
2 changes: 2 additions & 0 deletions src/modules/Workspaces/WorkspacesEditor/Data/ProjectData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ public struct ProjectWrapper

public bool IsShortcutNeeded { get; set; }

public bool IsLaunchOnStartup { get; set; }

public bool MoveExistingWindows { get; set; }

public List<MonitorConfigurationWrapper> MonitorConfiguration { get; set; }
Expand Down
4 changes: 4 additions & 0 deletions src/modules/Workspaces/WorkspacesEditor/Models/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public string Name

public bool IsShortcutNeeded { get; set; }

public bool IsLaunchOnStartup { get; set; }

public bool MoveExistingWindows { get; set; }

public string LastLaunched
Expand Down Expand Up @@ -205,6 +207,7 @@ public Project(Project selectedProject)
PreviewIcons = selectedProject.PreviewIcons;
PreviewImage = selectedProject.PreviewImage;
IsShortcutNeeded = selectedProject.IsShortcutNeeded;
IsLaunchOnStartup = selectedProject.IsLaunchOnStartup;
MoveExistingWindows = selectedProject.MoveExistingWindows;

int screenIndex = 1;
Expand Down Expand Up @@ -233,6 +236,7 @@ public Project(ProjectData.ProjectWrapper project)
CreationTime = project.CreationTime;
LastLaunchedTime = project.LastLaunchedTime;
IsShortcutNeeded = project.IsShortcutNeeded;
IsLaunchOnStartup = project.IsLaunchOnStartup;
MoveExistingWindows = project.MoveExistingWindows;
Monitors = [];
Applications = [];
Expand Down

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

Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@
<data name="CreateShortcut" xml:space="preserve">
<value>Create desktop shortcut</value>
</data>
<data name="ShouldLaunchOnStartup" xml:space="preserve">
<value>Launch on startup</value>
</data>
<data name="Custom" xml:space="preserve">
<value>Custom</value>
</data>
Expand Down
5 changes: 5 additions & 0 deletions src/modules/Workspaces/WorkspacesEditor/Utils/FolderUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ public static string Desktop()
return Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
}

public static string Startup()
{
return Environment.GetFolderPath(Environment.SpecialFolder.Startup);
}

public static string Temp()
{
return Path.GetTempPath();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public void SerializeWorkspaces(List<Project> workspaces, bool useTempFile = fal
Name = project.Name,
CreationTime = project.CreationTime,
IsShortcutNeeded = project.IsShortcutNeeded,
IsLaunchOnStartup = project.IsLaunchOnStartup,
MoveExistingWindows = project.MoveExistingWindows,
LastLaunchedTime = project.LastLaunchedTime,
Applications = [],
Expand Down
43 changes: 28 additions & 15 deletions src/modules/Workspaces/WorkspacesEditor/ViewModels/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ public void SaveProject(Project projectToSave)

editedProject.Name = projectToSave.Name;
editedProject.IsShortcutNeeded = projectToSave.IsShortcutNeeded;
editedProject.IsLaunchOnStartup = projectToSave.IsLaunchOnStartup;
editedProject.MoveExistingWindows = projectToSave.MoveExistingWindows;
editedProject.PreviewIcons = projectToSave.PreviewIcons;
editedProject.PreviewImage = projectToSave.PreviewImage;
Expand All @@ -194,36 +195,52 @@ public void SaveProject(Project projectToSave)

private void ApplyShortcut(Project project)
{
string basePath = AppDomain.CurrentDomain.BaseDirectory;
string shortcutAddress = Path.Combine(FolderUtils.Desktop(), project.Name + ".lnk");
string shortcutIconFilename = Path.Combine(FolderUtils.Temp(), project.Id + ".ico");

if (!project.IsShortcutNeeded)
if (!project.IsShortcutNeeded && !project.IsLaunchOnStartup)
{
if (File.Exists(shortcutIconFilename))
{
File.Delete(shortcutIconFilename);
}
}
else
{
Bitmap icon = WorkspacesIcon.DrawIcon(WorkspacesIcon.IconTextFromProjectName(project.Name), App.ThemeManager.GetCurrentTheme());
WorkspacesIcon.SaveIcon(icon, shortcutIconFilename);
}

try
{
CreateShortcut(project, project.IsShortcutNeeded, FolderUtils.Desktop(), shortcutIconFilename);
CreateShortcut(project, project.IsLaunchOnStartup, FolderUtils.Startup(), shortcutIconFilename);
}
catch (Exception ex)
{
Logger.LogError($"Shortcut creation error: {ex.Message}");
}
}

private void CreateShortcut(Project project, bool isNeeded, string shortcutFolder, string shortcutIconFilename)
{
string shortcutAddress = Path.Combine(shortcutFolder, project.Name + ".lnk");
if (!isNeeded)
{
if (File.Exists(shortcutAddress))
{
File.Delete(shortcutAddress);
}

return;
}

Bitmap icon = WorkspacesIcon.DrawIcon(WorkspacesIcon.IconTextFromProjectName(project.Name), App.ThemeManager.GetCurrentTheme());
WorkspacesIcon.SaveIcon(icon, shortcutIconFilename);

try
else
{
string basePath = AppDomain.CurrentDomain.BaseDirectory;

// Workaround to be able to create a shortcut with unicode filename
File.WriteAllBytes(shortcutAddress, Array.Empty<byte>());

// Create a ShellLinkObject that references the .lnk file
Shell32.Shell shell = new Shell32.Shell();
Shell32.Folder dir = shell.NameSpace(FolderUtils.Desktop());
Shell32.Folder dir = shell.NameSpace(shortcutFolder);
Shell32.FolderItem folderItem = dir.Items().Item($"{project.Name}.lnk");
Shell32.ShellLinkObject link = (Shell32.ShellLinkObject)folderItem.GetLink;

Expand All @@ -236,10 +253,6 @@ private void ApplyShortcut(Project project)

link.Save(shortcutAddress);
}
catch (Exception ex)
{
Logger.LogError($"Shortcut creation error: {ex.Message}");
}
}

public void SaveProjectName(Project project)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,12 @@
Content="{x:Static props:Resources.CreateShortcut}"
FontSize="14"
IsChecked="{Binding IsShortcutNeeded, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox
Margin="20,0,0,0"
VerticalAlignment="Bottom"
Content="{x:Static props:Resources.ShouldLaunchOnStartup}"
FontSize="14"
IsChecked="{Binding IsLaunchOnStartup, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox
Margin="20,0,0,0"
VerticalAlignment="Bottom"
Expand Down
7 changes: 7 additions & 0 deletions src/modules/Workspaces/WorkspacesLib/WorkspacesData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ namespace WorkspacesData
const static wchar_t* CreationTimeID = L"creation-time";
const static wchar_t* LastLaunchedTimeID = L"last-launched-time";
const static wchar_t* IsShortcutNeededID = L"is-shortcut-needed";
const static wchar_t* IsLaunchOnStartupID = L"is-Launch-on-startup";
const static wchar_t* MoveExistingWindowsID = L"move-existing-windows";
const static wchar_t* MonitorConfigurationID = L"monitor-configuration";
const static wchar_t* AppsID = L"applications";
Expand Down Expand Up @@ -312,6 +313,7 @@ namespace WorkspacesData
json.SetNamedValue(NonLocalizable::LastLaunchedTimeID, json::value(static_cast<long>(data.lastLaunchedTime.value())));
}
json.SetNamedValue(NonLocalizable::IsShortcutNeededID, json::value(data.isShortcutNeeded));
json.SetNamedValue(NonLocalizable::IsLaunchOnStartupID, json::value(data.isLaunchOnStartup));
json.SetNamedValue(NonLocalizable::MoveExistingWindowsID, json::value(data.moveExistingWindows));
json.SetNamedValue(NonLocalizable::MonitorConfigurationID, monitorsArray);
json.SetNamedValue(NonLocalizable::AppsID, appsArray);
Expand All @@ -338,6 +340,11 @@ namespace WorkspacesData
result.isShortcutNeeded = json.GetNamedBoolean(NonLocalizable::IsShortcutNeededID);
}

if (json.HasKey(NonLocalizable::IsLaunchOnStartupID))
{
result.isLaunchOnStartup = json.GetNamedBoolean(NonLocalizable::IsLaunchOnStartupID);
}

if (json.HasKey(NonLocalizable::MoveExistingWindowsID))
{
result.moveExistingWindows = json.GetNamedBoolean(NonLocalizable::MoveExistingWindowsID);
Expand Down
1 change: 1 addition & 0 deletions src/modules/Workspaces/WorkspacesLib/WorkspacesData.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ namespace WorkspacesData
time_t creationTime;
std::optional<time_t> lastLaunchedTime;
bool isShortcutNeeded;
bool isLaunchOnStartup;
bool moveExistingWindows;
std::vector<Monitor> monitors;
std::vector<Application> apps;
Expand Down

0 comments on commit a95d51b

Please sign in to comment.