From 385ae8fd65838317d45dfbcd900c51dcc936b1dd Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Wed, 21 Feb 2024 00:35:20 -0500 Subject: [PATCH 1/3] chore(www): upgrade `server-list` to Lit --- .../views/servers_view/server_list/index.ts | 87 ++++++++----------- 1 file changed, 38 insertions(+), 49 deletions(-) diff --git a/src/www/views/servers_view/server_list/index.ts b/src/www/views/servers_view/server_list/index.ts index 0accdc8e66..ecd8496c9e 100644 --- a/src/www/views/servers_view/server_list/index.ts +++ b/src/www/views/servers_view/server_list/index.ts @@ -11,64 +11,53 @@ limitations under the License. */ -import {computed, customElement, property} from '@polymer/decorators'; -import {html, PolymerElement} from '@polymer/polymer'; +import {css, html, LitElement} from 'lit'; +import {customElement, property} from 'lit/decorators.js'; import '../server_list_item/server_card'; import {ServerListItem} from '../server_list_item'; import {Localizer} from 'src/infrastructure/i18n'; @customElement('server-list') -export class ServerList extends PolymerElement { - static get template() { - return html` - - - - - `; - } - - // Need to declare localize function passed in from parent, or else - // localize() calls within the template won't be updated. - - // @polymer/decorators doesn't support Function constructors... - @property({type: Object}) localize: Localizer; +export class ServerList extends LitElement { + static styles = [ + css` + :host { + box-sizing: border-box; + display: block; + height: 100%; + margin: 0 auto; + padding: 8px; + width: 100%; + } + + server-row-card { + margin: 0 auto 8px auto; + height: 130px; + } + + server-hero-card { + height: 400px; + } + `, + ]; + + @property({type: Function}) localize: Localizer = msg => msg; @property({type: Array}) servers: ServerListItem[] = []; - @computed('servers') - get hasSingleServer() { - return this.servers.length === 1; + render() { + if (this.hasSingleServer) { + return html` `; + } else { + return html` + ${this.servers.map( + server => html`` + )} + `; + } } - getErrorMessage(errorMessageId: string) { - if (typeof errorMessageId === 'string') { - return this.localize(errorMessageId); - } + private get hasSingleServer() { + return this.servers.length === 1; } } From eaacd83900a079a84c6fe20fc1ce9affa9bdc331 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Wed, 21 Feb 2024 01:07:21 -0500 Subject: [PATCH 2/3] Fix the "floating" location of the popover on initial load. --- .../apple/xcode/macos/Outline/Classes/AppDelegate.m | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/cordova/apple/xcode/macos/Outline/Classes/AppDelegate.m b/src/cordova/apple/xcode/macos/Outline/Classes/AppDelegate.m index 2769ab4012..797794acaa 100644 --- a/src/cordova/apple/xcode/macos/Outline/Classes/AppDelegate.m +++ b/src/cordova/apple/xcode/macos/Outline/Classes/AppDelegate.m @@ -103,7 +103,16 @@ - (void)applicationDidFinishLaunching:(NSNotification*)aNotification { } }]; } else { - [self showPopover]; + // The rendering of the popover is relative to the app's status item in the status bar. + // Even though we've already created the status bar above, the popover is being created + // before the status item has been rendered in the UI. This causes the initial popover + // load to be "floating" and ends up aligned at the bottom of the screen. For this initial + // load we add a small artificial delay to prevent that from happening. + double delayInSeconds = 0.5; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); + dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ + [self showPopover]; + }); } [self setAppLauncherEnabled:true]; // Enable app launcher to start on boot. } From 166ae710c97dbc3b2f1300c665aa4d2d77cad2c0 Mon Sep 17 00:00:00 2001 From: Sander Bruens Date: Wed, 21 Feb 2024 01:13:42 -0500 Subject: [PATCH 3/3] Use the `NSPopover`'s native behavior to close the popover for us, instead of assuming responsibility for closing the popover in the app. --- .../apple/xcode/macos/Outline/Classes/AppDelegate.m | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/cordova/apple/xcode/macos/Outline/Classes/AppDelegate.m b/src/cordova/apple/xcode/macos/Outline/Classes/AppDelegate.m index 797794acaa..e8665261d9 100644 --- a/src/cordova/apple/xcode/macos/Outline/Classes/AppDelegate.m +++ b/src/cordova/apple/xcode/macos/Outline/Classes/AppDelegate.m @@ -85,16 +85,10 @@ - (void)applicationDidFinishLaunching:(NSNotification*)aNotification { self.statusItem.button.action = @selector(togglePopover); [self setAppIcon:@"StatusBarButtonImage"]; self.popover = [[NSPopover alloc] init]; + self.popover.behavior = NSPopoverBehaviorTransient; self.popover.contentViewController = [[NSViewController alloc] initWithNibName:@"MainViewController" bundle:[NSBundle mainBundle]]; self.popover.contentViewController.view = self.window.contentView; - // Monitor clicks outside the popover in order to close it. - NSEventMask eventMask = NSEventMaskLeftMouseDown|NSEventMaskRightMouseDown; - self.eventMonitor = [[EventMonitor alloc] initWithMask:eventMask handler:^(NSEvent* event) { - if (self.popover.isShown) { - [self closePopover]; - } - }]; if ([self wasStartedByLauncherApp]) { [OutlineVpn.shared startLastSuccessfulTunnel:^(enum ErrorCode errorCode) {