공개: 플랫폼 결론과 릴리즈 노트 규칙 반영
|
|
@ -12,10 +12,10 @@
|
|||
<Product>KoTalk</Product>
|
||||
<Description>한국어 중심의 차분한 메시징 경험을 다시 설계하는 Windows-first 메신저</Description>
|
||||
<AssemblyTitle>KoTalk</AssemblyTitle>
|
||||
<AssemblyVersion>0.1.0.5</AssemblyVersion>
|
||||
<FileVersion>0.1.0.5</FileVersion>
|
||||
<Version>0.1.0-alpha.5</Version>
|
||||
<InformationalVersion>0.1.0-alpha.5</InformationalVersion>
|
||||
<AssemblyVersion>0.1.0.6</AssemblyVersion>
|
||||
<FileVersion>0.1.0.6</FileVersion>
|
||||
<Version>0.1.0-alpha.6</Version>
|
||||
<InformationalVersion>0.1.0-alpha.6</InformationalVersion>
|
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ public partial class MainWindowViewModel : ViewModelBase, IAsyncDisposable
|
|||
$"desktop-{Environment.MachineName.ToLowerInvariant()}",
|
||||
"windows",
|
||||
Environment.MachineName,
|
||||
"0.1.0-alpha.5"));
|
||||
"0.1.0-alpha.6"));
|
||||
|
||||
var response = await _apiClient.RegisterAlphaQuickAsync(apiBaseUrl, request, CancellationToken.None);
|
||||
ApiBaseUrl = apiBaseUrl;
|
||||
|
|
|
|||
14
src/PhysOn.Mobile.Android/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:fullBackupContent="false"
|
||||
android:icon="@mipmap/appicon"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/appicon_round"
|
||||
android:supportsRtl="true"
|
||||
android:usesCleartextTraffic="false">
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
||||
268
src/PhysOn.Mobile.Android/MainActivity.cs
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.Graphics;
|
||||
using Android.Net;
|
||||
using Android.Net.Http;
|
||||
using Android.OS;
|
||||
using Android.Views;
|
||||
using Android.Webkit;
|
||||
using Android.Widget;
|
||||
|
||||
namespace PhysOn.Mobile.Android;
|
||||
|
||||
[Activity(
|
||||
Label = "@string/app_name",
|
||||
MainLauncher = true,
|
||||
Exported = true,
|
||||
LaunchMode = LaunchMode.SingleTask,
|
||||
Theme = "@style/KoTalkTheme",
|
||||
ConfigurationChanges =
|
||||
ConfigChanges.Orientation |
|
||||
ConfigChanges.ScreenSize |
|
||||
ConfigChanges.SmallestScreenSize |
|
||||
ConfigChanges.ScreenLayout |
|
||||
ConfigChanges.UiMode |
|
||||
ConfigChanges.KeyboardHidden |
|
||||
ConfigChanges.Density)]
|
||||
public class MainActivity : Activity
|
||||
{
|
||||
private const string AppVersion = "0.1.0-alpha.6";
|
||||
private const string HomeUrl = "https://vstalk.phy.kr";
|
||||
|
||||
private static readonly HashSet<string> AllowedHosts = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"vstalk.phy.kr",
|
||||
"download-vstalk.phy.kr"
|
||||
};
|
||||
|
||||
private WebView? _webView;
|
||||
private ProgressBar? _loadingBar;
|
||||
private View? _offlineOverlay;
|
||||
private ImageButton? _retryButton;
|
||||
|
||||
protected override void OnCreate(Bundle? savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
ConfigureWindowChrome();
|
||||
SetContentView(Resource.Layout.activity_main);
|
||||
|
||||
_webView = FindViewById<WebView>(Resource.Id.app_webview);
|
||||
_loadingBar = FindViewById<ProgressBar>(Resource.Id.loading_bar);
|
||||
_offlineOverlay = FindViewById<View>(Resource.Id.offline_overlay);
|
||||
_retryButton = FindViewById<ImageButton>(Resource.Id.retry_button);
|
||||
|
||||
if (_webView is null || _loadingBar is null || _offlineOverlay is null || _retryButton is null)
|
||||
{
|
||||
throw new InvalidOperationException("KoTalk Android shell layout failed to load.");
|
||||
}
|
||||
|
||||
_retryButton.Click += HandleRetryClick;
|
||||
ConfigureWebView(_webView, _loadingBar);
|
||||
|
||||
if (savedInstanceState is not null)
|
||||
{
|
||||
_webView.RestoreState(savedInstanceState);
|
||||
}
|
||||
else
|
||||
{
|
||||
_webView.LoadUrl(HomeUrl);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnSaveInstanceState(Bundle outState)
|
||||
{
|
||||
base.OnSaveInstanceState(outState);
|
||||
_webView?.SaveState(outState);
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
if (_retryButton is not null)
|
||||
{
|
||||
_retryButton.Click -= HandleRetryClick;
|
||||
}
|
||||
|
||||
if (_webView is not null)
|
||||
{
|
||||
_webView.StopLoading();
|
||||
_webView.Destroy();
|
||||
_webView = null;
|
||||
}
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
public override void OnBackPressed()
|
||||
{
|
||||
if (_webView?.CanGoBack() == true)
|
||||
{
|
||||
_webView.GoBack();
|
||||
return;
|
||||
}
|
||||
|
||||
#pragma warning disable CA1422
|
||||
base.OnBackPressed();
|
||||
#pragma warning restore CA1422
|
||||
}
|
||||
|
||||
private void HandleRetryClick(object? sender, EventArgs e)
|
||||
{
|
||||
_webView?.Reload();
|
||||
}
|
||||
|
||||
private void ConfigureWindowChrome()
|
||||
{
|
||||
Window?.AddFlags(WindowManagerFlags.DrawsSystemBarBackgrounds);
|
||||
|
||||
if (Window is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Window.SetStatusBarColor(Color.ParseColor("#F7F3EE"));
|
||||
Window.SetNavigationBarColor(Color.ParseColor("#F7F3EE"));
|
||||
}
|
||||
|
||||
private void ConfigureWebView(WebView webView, ProgressBar loadingBar)
|
||||
{
|
||||
WebView.SetWebContentsDebuggingEnabled(System.Diagnostics.Debugger.IsAttached);
|
||||
|
||||
var settings = webView.Settings!;
|
||||
settings.JavaScriptEnabled = true;
|
||||
settings.DomStorageEnabled = true;
|
||||
settings.DatabaseEnabled = true;
|
||||
settings.AllowFileAccess = false;
|
||||
settings.AllowContentAccess = false;
|
||||
settings.SetSupportZoom(false);
|
||||
settings.BuiltInZoomControls = false;
|
||||
settings.DisplayZoomControls = false;
|
||||
settings.LoadWithOverviewMode = true;
|
||||
settings.UseWideViewPort = true;
|
||||
settings.MixedContentMode = MixedContentHandling.NeverAllow;
|
||||
settings.CacheMode = CacheModes.Default;
|
||||
settings.MediaPlaybackRequiresUserGesture = true;
|
||||
settings.UserAgentString = $"{settings.UserAgentString} KoTalkAndroid/{AppVersion}";
|
||||
|
||||
var cookies = CookieManager.Instance;
|
||||
cookies?.SetAcceptCookie(true);
|
||||
cookies?.SetAcceptThirdPartyCookies(webView, false);
|
||||
|
||||
webView.SetBackgroundColor(Color.ParseColor("#F7F3EE"));
|
||||
webView.SetWebChromeClient(new KoTalkWebChromeClient(loadingBar));
|
||||
webView.SetWebViewClient(
|
||||
new KoTalkWebViewClient(
|
||||
AllowedHosts,
|
||||
ShowOfflineOverlay,
|
||||
HideOfflineOverlay));
|
||||
}
|
||||
|
||||
private void ShowOfflineOverlay()
|
||||
{
|
||||
RunOnUiThread(() =>
|
||||
{
|
||||
if (_offlineOverlay is not null)
|
||||
{
|
||||
_offlineOverlay.Visibility = ViewStates.Visible;
|
||||
}
|
||||
|
||||
if (_loadingBar is not null)
|
||||
{
|
||||
_loadingBar.Visibility = ViewStates.Invisible;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void HideOfflineOverlay()
|
||||
{
|
||||
RunOnUiThread(() =>
|
||||
{
|
||||
if (_offlineOverlay is not null)
|
||||
{
|
||||
_offlineOverlay.Visibility = ViewStates.Gone;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private sealed class KoTalkWebChromeClient(ProgressBar loadingBar) : WebChromeClient
|
||||
{
|
||||
public override void OnProgressChanged(WebView? view, int newProgress)
|
||||
{
|
||||
base.OnProgressChanged(view, newProgress);
|
||||
loadingBar.Progress = newProgress;
|
||||
loadingBar.Visibility = newProgress >= 100 ? ViewStates.Invisible : ViewStates.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class KoTalkWebViewClient(
|
||||
IReadOnlySet<string> allowedHosts,
|
||||
Action showOfflineOverlay,
|
||||
Action hideOfflineOverlay) : WebViewClient
|
||||
{
|
||||
public override bool ShouldOverrideUrlLoading(WebView? view, IWebResourceRequest? request)
|
||||
{
|
||||
if (request?.Url is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var url = request.Url;
|
||||
var scheme = url.Scheme?.ToLowerInvariant();
|
||||
var host = url.Host?.ToLowerInvariant();
|
||||
|
||||
if (scheme is "http" or "https" && host is not null && allowedHosts.Contains(host))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (view?.Context is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var intent = new Intent(Intent.ActionView, global::Android.Net.Uri.Parse(url.ToString()));
|
||||
intent.AddFlags(ActivityFlags.NewTask);
|
||||
view.Context.StartActivity(intent);
|
||||
}
|
||||
catch (ActivityNotFoundException)
|
||||
{
|
||||
showOfflineOverlay();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void OnPageStarted(WebView? view, string? url, Bitmap? favicon)
|
||||
{
|
||||
base.OnPageStarted(view, url, favicon);
|
||||
hideOfflineOverlay();
|
||||
}
|
||||
|
||||
public override void OnPageFinished(WebView? view, string? url)
|
||||
{
|
||||
base.OnPageFinished(view, url);
|
||||
hideOfflineOverlay();
|
||||
}
|
||||
|
||||
public override void OnReceivedError(
|
||||
WebView? view,
|
||||
IWebResourceRequest? request,
|
||||
WebResourceError? error)
|
||||
{
|
||||
base.OnReceivedError(view, request, error);
|
||||
|
||||
if (request?.IsForMainFrame ?? true)
|
||||
{
|
||||
showOfflineOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnReceivedSslError(WebView? view, SslErrorHandler? handler, SslError? error)
|
||||
{
|
||||
handler?.Cancel();
|
||||
showOfflineOverlay();
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/PhysOn.Mobile.Android/PhysOn.Mobile.Android.csproj
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-android</TargetFramework>
|
||||
<SupportedOSPlatformVersion>26</SupportedOSPlatformVersion>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<RootNamespace>PhysOn.Mobile.Android</RootNamespace>
|
||||
<AssemblyName>KoTalk.Mobile.Android</AssemblyName>
|
||||
<ApplicationId>kr.physia.kotalk</ApplicationId>
|
||||
<ApplicationVersion>6</ApplicationVersion>
|
||||
<ApplicationDisplayVersion>0.1.0-alpha.6</ApplicationDisplayVersion>
|
||||
<Company>PHYSIA</Company>
|
||||
<Authors>PHYSIA</Authors>
|
||||
<Product>KoTalk</Product>
|
||||
<Description>KoTalk Android shell for the live Korean messaging experience</Description>
|
||||
<ApplicationTitle>KoTalk</ApplicationTitle>
|
||||
<AndroidPackageFormat>apk</AndroidPackageFormat>
|
||||
<AndroidUseDesignerAssembly>false</AndroidUseDesignerAssembly>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(JavaSdkDirectory)' == '' and '$(JAVA_HOME)' != ''">
|
||||
<JavaSdkDirectory>$(JAVA_HOME)</JavaSdkDirectory>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(JavaSdkDirectory)' == '' and Exists('/usr/lib/jvm/java-17-openjdk-amd64')">
|
||||
<JavaSdkDirectory>/usr/lib/jvm/java-17-openjdk-amd64</JavaSdkDirectory>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(AndroidSdkDirectory)' == '' and '$(ANDROID_SDK_ROOT)' != ''">
|
||||
<AndroidSdkDirectory>$(ANDROID_SDK_ROOT)</AndroidSdkDirectory>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(AndroidSdkDirectory)' == '' and Exists('$([System.Environment]::GetEnvironmentVariable(`HOME`))/Android/Sdk')">
|
||||
<AndroidSdkDirectory>$([System.Environment]::GetEnvironmentVariable('HOME'))/Android/Sdk</AndroidSdkDirectory>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
44
src/PhysOn.Mobile.Android/Resources/AboutResources.txt
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
Images, layout descriptions, binary blobs and string dictionaries can be included
|
||||
in your application as resource files. Various Android APIs are designed to
|
||||
operate on the resource IDs instead of dealing with images, strings or binary blobs
|
||||
directly.
|
||||
|
||||
For example, a sample Android app that contains a user interface layout (main.xml),
|
||||
an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
|
||||
would keep its resources in the "Resources" directory of the application:
|
||||
|
||||
Resources/
|
||||
drawable/
|
||||
icon.png
|
||||
|
||||
layout/
|
||||
main.xml
|
||||
|
||||
values/
|
||||
strings.xml
|
||||
|
||||
In order to get the build system to recognize Android resources, set the build action to
|
||||
"AndroidResource". The native Android APIs do not operate directly with filenames, but
|
||||
instead operate on resource IDs. When you compile an Android application that uses resources,
|
||||
the build system will package the resources for distribution and generate a class called "Resource"
|
||||
(this is an Android convention) that contains the tokens for each one of the resources
|
||||
included. For example, for the above Resources layout, this is what the Resource class would expose:
|
||||
|
||||
public class Resource {
|
||||
public class Drawable {
|
||||
public const int icon = 0x123;
|
||||
}
|
||||
|
||||
public class Layout {
|
||||
public const int main = 0x456;
|
||||
}
|
||||
|
||||
public class Strings {
|
||||
public const int first_string = 0xabc;
|
||||
public const int second_string = 0xbcd;
|
||||
}
|
||||
}
|
||||
|
||||
You would then use Resource.Drawable.icon to reference the drawable/icon.png file, or
|
||||
Resource.Layout.main to reference the layout/main.xml file, or Resource.Strings.first_string
|
||||
to reference the first string in the dictionary file values/strings.xml.
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<solid android:color="@color/surface_card" />
|
||||
<stroke android:width="1dp" android:color="@color/surface_border" />
|
||||
<corners android:radius="2dp" />
|
||||
</shape>
|
||||
52
src/PhysOn.Mobile.Android/Resources/layout/activity_main.xml
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/surface_canvas">
|
||||
|
||||
<WebView
|
||||
android:id="@+id/app_webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:importantForAutofill="noExcludeDescendants"
|
||||
android:overScrollMode="never" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/loading_bar"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="3dp"
|
||||
android:layout_gravity="top"
|
||||
android:indeterminate="false"
|
||||
android:max="100"
|
||||
android:progressBackgroundTint="@color/surface_border"
|
||||
android:progressTint="@color/accent_primary"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/offline_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="28dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_marginBottom="20dp"
|
||||
android:contentDescription="@string/app_name"
|
||||
android:src="@mipmap/appicon" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/retry_button"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="56dp"
|
||||
android:background="@drawable/retry_button_background"
|
||||
android:contentDescription="@string/reload"
|
||||
android:padding="16dp"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@android:drawable/ic_popup_sync" />
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@mipmap/appicon_background" />
|
||||
<foreground android:drawable="@mipmap/appicon_foreground" />
|
||||
</adaptive-icon>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@mipmap/appicon_background" />
|
||||
<foreground android:drawable="@mipmap/appicon_foreground" />
|
||||
</adaptive-icon>
|
||||
BIN
src/PhysOn.Mobile.Android/Resources/mipmap-hdpi/appicon.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 229 B |
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/PhysOn.Mobile.Android/Resources/mipmap-mdpi/appicon.png
Normal file
|
After Width: | Height: | Size: 940 B |
|
After Width: | Height: | Size: 142 B |
|
After Width: | Height: | Size: 1,010 B |
BIN
src/PhysOn.Mobile.Android/Resources/mipmap-xhdpi/appicon.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 295 B |
|
After Width: | Height: | Size: 1.8 KiB |
BIN
src/PhysOn.Mobile.Android/Resources/mipmap-xxhdpi/appicon.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 436 B |
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/PhysOn.Mobile.Android/Resources/mipmap-xxxhdpi/appicon.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 594 B |
|
After Width: | Height: | Size: 3.3 KiB |
8
src/PhysOn.Mobile.Android/Resources/values/colors.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="surface_canvas">#F7F3EE</color>
|
||||
<color name="surface_card">#FFFFFF</color>
|
||||
<color name="surface_border">#DDD1C4</color>
|
||||
<color name="ink_primary">#20242B</color>
|
||||
<color name="accent_primary">#F05B2B</color>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#2C3E50</color>
|
||||
</resources>
|
||||
4
src/PhysOn.Mobile.Android/Resources/values/strings.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<resources>
|
||||
<string name="app_name">KoTalk</string>
|
||||
<string name="reload">다시 불러오기</string>
|
||||
</resources>
|
||||
8
src/PhysOn.Mobile.Android/Resources/values/styles.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="KoTalkTheme" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar">
|
||||
<item name="android:windowBackground">@color/surface_canvas</item>
|
||||
<item name="android:statusBarColor">@color/surface_canvas</item>
|
||||
<item name="android:navigationBarColor">@color/surface_canvas</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="false" />
|
||||
</network-security-config>
|
||||
4
src/PhysOn.Web/package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "physon-web",
|
||||
"version": "0.1.0-alpha.5",
|
||||
"version": "0.1.0-alpha.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "physon-web",
|
||||
"version": "0.1.0-alpha.5",
|
||||
"version": "0.1.0-alpha.6",
|
||||
"dependencies": {
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "physon-web",
|
||||
"private": true,
|
||||
"version": "0.1.0-alpha.5",
|
||||
"version": "0.1.0-alpha.6",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --host 0.0.0.0",
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ type IconName =
|
|||
| 'group'
|
||||
|
||||
const DEFAULT_API_BASE_URL = import.meta.env.VITE_API_BASE_URL?.trim() ?? ''
|
||||
const APP_VERSION = 'web-0.1.0-alpha.5'
|
||||
const APP_VERSION = 'web-0.1.0-alpha.6'
|
||||
|
||||
const CONNECTION_LABEL: Record<ConnectionState, string> = {
|
||||
idle: '준비 중',
|
||||
|
|
|
|||