PyWebWinUI3 1.1.0__tar.gz → 1.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. {pywebwinui3-1.1.0/PyWebWinUI3.egg-info → pywebwinui3-1.2.1}/PKG-INFO +1 -1
  2. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1/PyWebWinUI3.egg-info}/PKG-INFO +1 -1
  3. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/PyWebWinUI3.egg-info/SOURCES.txt +6 -6
  4. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/__init__.py +1 -1
  5. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/core.py +169 -3
  6. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/util.py +122 -3
  7. pywebwinui3-1.1.0/pywebwinui3/web/_app/immutable/assets/2.DFa7Tulp.css → pywebwinui3-1.2.1/pywebwinui3/web/_app/immutable/assets/2.B-R7-woU.css +1 -1
  8. pywebwinui3-1.2.1/pywebwinui3/web/_app/immutable/chunks/CDNCM73h.js +1 -0
  9. pywebwinui3-1.1.0/pywebwinui3/web/_app/immutable/entry/app.COvDX_WQ.js → pywebwinui3-1.2.1/pywebwinui3/web/_app/immutable/entry/app.DZs-LPnH.js +2 -2
  10. pywebwinui3-1.2.1/pywebwinui3/web/_app/immutable/entry/start.BIkwzMz6.js +1 -0
  11. pywebwinui3-1.1.0/pywebwinui3/web/_app/immutable/nodes/1.Qo_2yB_V.js → pywebwinui3-1.2.1/pywebwinui3/web/_app/immutable/nodes/1.CrcwixmX.js +1 -1
  12. pywebwinui3-1.2.1/pywebwinui3/web/_app/immutable/nodes/2.BX-aQgy_.js +99 -0
  13. pywebwinui3-1.2.1/pywebwinui3/web/_app/version.json +1 -0
  14. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/index.html +8 -8
  15. pywebwinui3-1.1.0/pywebwinui3/web/_app/immutable/chunks/BrxDGwA4.js +0 -1
  16. pywebwinui3-1.1.0/pywebwinui3/web/_app/immutable/entry/start.D-PUi8dH.js +0 -1
  17. pywebwinui3-1.1.0/pywebwinui3/web/_app/immutable/nodes/2.DAAD9EkZ.js +0 -98
  18. pywebwinui3-1.1.0/pywebwinui3/web/_app/version.json +0 -1
  19. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/LICENSE +0 -0
  20. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/MANIFEST.in +0 -0
  21. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/NOTICE +0 -0
  22. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/PyWebWinUI3.egg-info/dependency_links.txt +0 -0
  23. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/PyWebWinUI3.egg-info/requires.txt +0 -0
  24. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/PyWebWinUI3.egg-info/top_level.txt +0 -0
  25. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/README.md +0 -0
  26. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pyproject.toml +0 -0
  27. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/event.py +0 -0
  28. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/type.py +0 -0
  29. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.0.woff2 +0 -0
  30. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.1.woff2 +0 -0
  31. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.10.woff2 +0 -0
  32. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.11.woff2 +0 -0
  33. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.12.woff2 +0 -0
  34. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.13.woff2 +0 -0
  35. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.14.woff2 +0 -0
  36. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.15.woff2 +0 -0
  37. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.16.woff2 +0 -0
  38. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.17.woff2 +0 -0
  39. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.18.woff2 +0 -0
  40. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.19.woff2 +0 -0
  41. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.2.woff2 +0 -0
  42. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.20.woff2 +0 -0
  43. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.21.woff2 +0 -0
  44. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.22.woff2 +0 -0
  45. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.23.woff2 +0 -0
  46. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.24.woff2 +0 -0
  47. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.25.woff2 +0 -0
  48. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.26.woff2 +0 -0
  49. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.27.woff2 +0 -0
  50. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.28.woff2 +0 -0
  51. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.29.woff2 +0 -0
  52. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.3.woff2 +0 -0
  53. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.30.woff2 +0 -0
  54. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.31.woff2 +0 -0
  55. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.32.woff2 +0 -0
  56. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.33.woff2 +0 -0
  57. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.34.woff2 +0 -0
  58. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.35.woff2 +0 -0
  59. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.36.woff2 +0 -0
  60. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.37.woff2 +0 -0
  61. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.38.woff2 +0 -0
  62. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.39.woff2 +0 -0
  63. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.4.woff2 +0 -0
  64. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.40.woff2 +0 -0
  65. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.41.woff2 +0 -0
  66. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.42.woff2 +0 -0
  67. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.43.woff2 +0 -0
  68. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.44.woff2 +0 -0
  69. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.45.woff2 +0 -0
  70. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.46.woff2 +0 -0
  71. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.47.woff2 +0 -0
  72. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.48.woff2 +0 -0
  73. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.49.woff2 +0 -0
  74. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.5.woff2 +0 -0
  75. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.50.woff2 +0 -0
  76. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.51.woff2 +0 -0
  77. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.52.woff2 +0 -0
  78. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.53.woff2 +0 -0
  79. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.54.woff2 +0 -0
  80. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.55.woff2 +0 -0
  81. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.56.woff2 +0 -0
  82. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.57.woff2 +0 -0
  83. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.58.woff2 +0 -0
  84. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.59.woff2 +0 -0
  85. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.6.woff2 +0 -0
  86. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.60.woff2 +0 -0
  87. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.61.woff2 +0 -0
  88. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.62.woff2 +0 -0
  89. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.63.woff2 +0 -0
  90. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.64.woff2 +0 -0
  91. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.65.woff2 +0 -0
  92. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.66.woff2 +0 -0
  93. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.67.woff2 +0 -0
  94. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.68.woff2 +0 -0
  95. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.69.woff2 +0 -0
  96. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.7.woff2 +0 -0
  97. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.70.woff2 +0 -0
  98. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.71.woff2 +0 -0
  99. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.72.woff2 +0 -0
  100. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.73.woff2 +0 -0
  101. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.74.woff2 +0 -0
  102. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.75.woff2 +0 -0
  103. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.76.woff2 +0 -0
  104. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.77.woff2 +0 -0
  105. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.78.woff2 +0 -0
  106. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.79.woff2 +0 -0
  107. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.8.woff2 +0 -0
  108. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.80.woff2 +0 -0
  109. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.81.woff2 +0 -0
  110. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.82.woff2 +0 -0
  111. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.83.woff2 +0 -0
  112. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.84.woff2 +0 -0
  113. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.85.woff2 +0 -0
  114. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.86.woff2 +0 -0
  115. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.87.woff2 +0 -0
  116. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.88.woff2 +0 -0
  117. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.89.woff2 +0 -0
  118. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.9.woff2 +0 -0
  119. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.90.woff2 +0 -0
  120. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/PretendardVariable.subset.91.woff2 +0 -0
  121. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/Pretendard/Variable-dynamic-subset.min.css +0 -0
  122. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/SegoeFluentIcons.ttf +0 -0
  123. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/_app/env.js +0 -0
  124. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/_app/immutable/chunks/6pQH9Hkv.js +0 -0
  125. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/_app/immutable/chunks/B-XLOWlt.js +0 -0
  126. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/_app/immutable/chunks/CGGCsFu4.js +0 -0
  127. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/_app/immutable/chunks/CW0wlPPy.js +0 -0
  128. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/_app/immutable/chunks/CZPLFskb.js +0 -0
  129. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/_app/immutable/chunks/CZuXpvpo.js +0 -0
  130. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/_app/immutable/chunks/DF1x2LYX.js +0 -0
  131. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/pywebwinui3/web/_app/immutable/nodes/0.C49PHrK2.js +0 -0
  132. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/requirements.txt +0 -0
  133. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/setup.cfg +0 -0
  134. {pywebwinui3-1.1.0 → pywebwinui3-1.2.1}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyWebWinUI3
3
- Version: 1.1.0
3
+ Version: 1.2.1
4
4
  Summary: Create modern WinUI3-style desktop UIs in Python using pywebview and a Svelte frontend.
5
5
  Home-page: https://github.com/Haruna5718/PyWebWinUI3
6
6
  Author: Haruna5718
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyWebWinUI3
3
- Version: 1.1.0
3
+ Version: 1.2.1
4
4
  Summary: Create modern WinUI3-style desktop UIs in Python using pywebview and a Svelte frontend.
5
5
  Home-page: https://github.com/Haruna5718/PyWebWinUI3
6
6
  Author: Haruna5718
@@ -112,17 +112,17 @@ pywebwinui3/web/Pretendard/PretendardVariable.subset.91.woff2
112
112
  pywebwinui3/web/Pretendard/Variable-dynamic-subset.min.css
113
113
  pywebwinui3/web/_app/env.js
114
114
  pywebwinui3/web/_app/version.json
115
- pywebwinui3/web/_app/immutable/assets/2.DFa7Tulp.css
115
+ pywebwinui3/web/_app/immutable/assets/2.B-R7-woU.css
116
116
  pywebwinui3/web/_app/immutable/chunks/6pQH9Hkv.js
117
117
  pywebwinui3/web/_app/immutable/chunks/B-XLOWlt.js
118
- pywebwinui3/web/_app/immutable/chunks/BrxDGwA4.js
118
+ pywebwinui3/web/_app/immutable/chunks/CDNCM73h.js
119
119
  pywebwinui3/web/_app/immutable/chunks/CGGCsFu4.js
120
120
  pywebwinui3/web/_app/immutable/chunks/CW0wlPPy.js
121
121
  pywebwinui3/web/_app/immutable/chunks/CZPLFskb.js
122
122
  pywebwinui3/web/_app/immutable/chunks/CZuXpvpo.js
123
123
  pywebwinui3/web/_app/immutable/chunks/DF1x2LYX.js
124
- pywebwinui3/web/_app/immutable/entry/app.COvDX_WQ.js
125
- pywebwinui3/web/_app/immutable/entry/start.D-PUi8dH.js
124
+ pywebwinui3/web/_app/immutable/entry/app.DZs-LPnH.js
125
+ pywebwinui3/web/_app/immutable/entry/start.BIkwzMz6.js
126
126
  pywebwinui3/web/_app/immutable/nodes/0.C49PHrK2.js
127
- pywebwinui3/web/_app/immutable/nodes/1.Qo_2yB_V.js
128
- pywebwinui3/web/_app/immutable/nodes/2.DAAD9EkZ.js
127
+ pywebwinui3/web/_app/immutable/nodes/1.CrcwixmX.js
128
+ pywebwinui3/web/_app/immutable/nodes/2.BX-aQgy_.js
@@ -1,3 +1,3 @@
1
1
  __all__ = ["core", "event", "util", "type"]
2
2
 
3
- __version__ = '1.1.0'
3
+ __version__ = '1.2.1'
@@ -3,9 +3,15 @@ from __future__ import annotations
3
3
  import importlib
4
4
  import json
5
5
  import logging
6
+ import mimetypes
7
+ import os
8
+ import re
6
9
  import sys
7
10
  import threading
11
+ from http import HTTPStatus
12
+ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
8
13
  from pathlib import Path
14
+ from urllib.parse import unquote, urlparse, urlunparse
9
15
 
10
16
  import webview
11
17
  from hPyT import title_bar
@@ -23,6 +29,63 @@ DEFAULT_WINDOW_MIN_WIDTH = 100
23
29
  DEFAULT_WINDOW_MIN_HEIGHT = 100
24
30
 
25
31
 
32
+ def _default_ui_origin_host(title: str) -> str:
33
+ slug = re.sub(r"[^a-z0-9]+", "-", str(title).casefold()).strip("-")
34
+ if not slug:
35
+ slug = "app"
36
+ slug = re.sub(r"-{2,}", "-", slug)[:48].strip("-")
37
+ if not slug:
38
+ slug = "app"
39
+ return f"{slug}.local"
40
+
41
+
42
+ class _UiHttpServer(ThreadingHTTPServer):
43
+ daemon_threads = True
44
+ allow_reuse_address = True
45
+
46
+ def __init__(self, server_address, request_handler_class, main: "MainWindow"):
47
+ super().__init__(server_address, request_handler_class)
48
+ self.main = main
49
+
50
+
51
+ class _UiRequestHandler(BaseHTTPRequestHandler):
52
+ server: _UiHttpServer
53
+
54
+ def do_GET(self):
55
+ try:
56
+ path = self.server.main._resolve_server_path(urlparse(self.path).path)
57
+ if path is None or not path.is_file():
58
+ self._send_error("Not found.", HTTPStatus.NOT_FOUND)
59
+ return
60
+
61
+ body = path.read_bytes()
62
+ content_type = mimetypes.guess_type(path.name)[0] or "application/octet-stream"
63
+ self.send_response(HTTPStatus.OK)
64
+ self._send_common_headers(content_type)
65
+ self.send_header("Content-Length", str(len(body)))
66
+ self.end_headers()
67
+ self.wfile.write(body)
68
+ except Exception:
69
+ core_logger.debug("Failed to serve UI asset", exc_info=True)
70
+ self._send_error("Failed to serve UI asset.", HTTPStatus.INTERNAL_SERVER_ERROR)
71
+
72
+ def log_message(self, format, *args):
73
+ return
74
+
75
+ def _send_error(self, message: str, status: HTTPStatus):
76
+ body = message.encode("utf-8")
77
+ self.send_response(status)
78
+ self._send_common_headers("text/plain; charset=utf-8")
79
+ self.send_header("Content-Length", str(len(body)))
80
+ self.end_headers()
81
+ self.wfile.write(body)
82
+
83
+ def _send_common_headers(self, content_type: str):
84
+ self.send_header("Content-Type", content_type)
85
+ self.send_header("Cache-Control", "no-store")
86
+ self.send_header("Permissions-Policy", "display-capture=*")
87
+
88
+
26
89
  class _JsApi:
27
90
  def _init(self, main:MainWindow):
28
91
  self.init = main._init_payload
@@ -58,6 +121,15 @@ class MainWindow:
58
121
  self._minimum_height = DEFAULT_WINDOW_MIN_HEIGHT
59
122
  self._sync_lock = threading.Lock()
60
123
  self._pending_sync: dict[str, object] = {}
124
+ self._ui_server: _UiHttpServer | None = None
125
+ self._ui_server_thread: threading.Thread | None = None
126
+ self._ui_origin = ""
127
+ self._ui_bind_host = "127.0.0.1"
128
+ self._ui_origin_host = getattr(self, "ui_origin_host", _default_ui_origin_host(title))
129
+ self._resource_roots: list[tuple[str, Path]] = [
130
+ ("root", self.rootPath),
131
+ ("package", self.packagePath),
132
+ ]
61
133
 
62
134
  self.values = SyncDict(
63
135
  {
@@ -72,10 +144,12 @@ class MainWindow:
72
144
  }
73
145
  )
74
146
  self.values.sync = self.queue_sync_value
147
+ self._start_ui_server()
148
+ self._configure_webview2_origin_identity()
75
149
 
76
150
  self._window = webview.create_window(
77
151
  self._current_title(),
78
- self._entry_path().as_uri(),
152
+ f"{self._ui_origin}/index.html",
79
153
  js_api=self.api,
80
154
  background_color="#202020",
81
155
  text_select=True,
@@ -178,6 +252,80 @@ class MainWindow:
178
252
  raise FileNotFoundError(f"Frontend entry not found: {entry}")
179
253
  return entry
180
254
 
255
+ def _start_ui_server(self):
256
+ self._ui_server = _UiHttpServer((self._ui_bind_host, 0), _UiRequestHandler, self)
257
+ self._ui_origin = f"http://{self._ui_origin_host}:{self._ui_server.server_port}"
258
+ self._ui_server_thread = threading.Thread(target=self._ui_server.serve_forever, daemon=True)
259
+ self._ui_server_thread.start()
260
+
261
+ def _configure_webview2_origin_identity(self):
262
+ if self._ui_origin_host == self._ui_bind_host:
263
+ return
264
+
265
+ parsed = urlparse(self._ui_origin)
266
+ if not parsed.scheme or parsed.port is None:
267
+ return
268
+
269
+ required_args = [
270
+ f'--host-resolver-rules="MAP {self._ui_origin_host} {self._ui_bind_host}"',
271
+ f"--unsafely-treat-insecure-origin-as-secure={parsed.scheme}://{self._ui_origin_host}:{parsed.port}",
272
+ ]
273
+ existing = os.environ.get("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "").strip()
274
+ missing = [arg for arg in required_args if arg not in existing]
275
+ if missing:
276
+ os.environ["WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS"] = " ".join(
277
+ [value for value in [existing, *missing] if value]
278
+ ).strip()
279
+
280
+ def _stop_ui_server(self):
281
+ if self._ui_server is None:
282
+ return
283
+ try:
284
+ self._ui_server.shutdown()
285
+ self._ui_server.server_close()
286
+ except Exception:
287
+ core_logger.debug("Failed to stop UI server", exc_info=True)
288
+ finally:
289
+ self._ui_server = None
290
+ self._ui_server_thread = None
291
+
292
+ def _resolve_path_under(self, base_path: Path, relative_path: str) -> Path | None:
293
+ candidate = (base_path / relative_path).resolve()
294
+ try:
295
+ candidate.relative_to(base_path)
296
+ except ValueError:
297
+ return None
298
+ return candidate
299
+
300
+ def _resolve_server_path(self, raw_path: str) -> Path | None:
301
+ path = unquote(raw_path or "/")
302
+ if path in {"", "/"}:
303
+ return self._entry_path()
304
+
305
+ for name, base_path in self._resource_roots:
306
+ if name == "package":
307
+ continue
308
+
309
+ prefix = f"/__{name}__/"
310
+ if path.startswith(prefix):
311
+ return self._resolve_path_under(base_path, path[len(prefix) :])
312
+
313
+ return self._resolve_path_under(self.packagePath, path.lstrip("/"))
314
+
315
+ def _resource_url(self, path: Path) -> str:
316
+ path = path.resolve()
317
+ for name, base_path in self._resource_roots:
318
+ try:
319
+ relative = path.relative_to(base_path)
320
+ except ValueError:
321
+ continue
322
+
323
+ if name == "package":
324
+ return f"{self._ui_origin}/{relative.as_posix()}"
325
+ return f"{self._ui_origin}/__{name}__/{relative.as_posix()}"
326
+
327
+ raise ValueError(f"Path is outside of registered resource roots: {path}")
328
+
181
329
  def _before_show(self):
182
330
  try:
183
331
  hwnd = self._window.native.Handle.ToInt64()
@@ -186,6 +334,8 @@ class MainWindow:
186
334
  core_logger.debug("Failed to hide title bar", exc_info=True)
187
335
 
188
336
  def _on_closed(self):
337
+ self.accent.stop()
338
+ self._stop_ui_server()
189
339
  self.events.closed.set()
190
340
 
191
341
  def _dispatch_or_defer_sync(self, key: str, value):
@@ -286,11 +436,27 @@ class MainWindow:
286
436
  if lowered.startswith(("http://", "https://", "file://", "data:", "about:")):
287
437
  return raw_value
288
438
 
289
- resolved = self.resolve_path(raw_value)
439
+ parsed = urlparse(raw_value)
440
+ path_value = parsed.path or raw_value
441
+ resolved = self.resolve_path(path_value)
290
442
  if resolved is None or not resolved.exists() or not resolved.is_file():
291
443
  return raw_value
292
444
 
293
- return resolved.resolve().as_uri()
445
+ resource_url = self._resource_url(resolved)
446
+ if not parsed.scheme and (parsed.query or parsed.fragment):
447
+ resource_parts = urlparse(resource_url)
448
+ resource_url = urlunparse(
449
+ (
450
+ resource_parts.scheme,
451
+ resource_parts.netloc,
452
+ resource_parts.path,
453
+ resource_parts.params,
454
+ parsed.query,
455
+ parsed.fragment,
456
+ )
457
+ )
458
+
459
+ return resource_url
294
460
 
295
461
  def start(
296
462
  self,
@@ -1,14 +1,57 @@
1
+ import ctypes
2
+ import logging
3
+ import threading
4
+ import winreg
1
5
  import xml.etree.ElementTree
2
6
  from functools import lru_cache
3
7
  from typing import Any, Callable
4
- import winreg
5
- import logging
6
8
  import re
9
+ from ctypes import wintypes
7
10
 
8
11
  from .event import PathEvent, Event
9
12
 
10
13
  logger = logging.getLogger('pywebwinui3.util')
11
14
 
15
+ ACCENT_REGISTRY_PATH = r"Software\Microsoft\Windows\CurrentVersion\Explorer\Accent"
16
+ REG_NOTIFY_CHANGE_LAST_SET = 0x00000004
17
+ WAIT_OBJECT_0 = 0x00000000
18
+ WAIT_FAILED = 0xFFFFFFFF
19
+ INFINITE = 0xFFFFFFFF
20
+
21
+ _advapi32 = ctypes.WinDLL("Advapi32", use_last_error=True)
22
+ _kernel32 = ctypes.WinDLL("Kernel32", use_last_error=True)
23
+
24
+ _advapi32.RegNotifyChangeKeyValue.argtypes = [
25
+ wintypes.HKEY,
26
+ wintypes.BOOL,
27
+ wintypes.DWORD,
28
+ wintypes.HANDLE,
29
+ wintypes.BOOL,
30
+ ]
31
+ _advapi32.RegNotifyChangeKeyValue.restype = wintypes.LONG
32
+
33
+ _kernel32.CreateEventW.argtypes = [
34
+ wintypes.LPVOID,
35
+ wintypes.BOOL,
36
+ wintypes.BOOL,
37
+ wintypes.LPCWSTR,
38
+ ]
39
+ _kernel32.CreateEventW.restype = wintypes.HANDLE
40
+
41
+ _kernel32.SetEvent.argtypes = [wintypes.HANDLE]
42
+ _kernel32.SetEvent.restype = wintypes.BOOL
43
+
44
+ _kernel32.CloseHandle.argtypes = [wintypes.HANDLE]
45
+ _kernel32.CloseHandle.restype = wintypes.BOOL
46
+
47
+ _kernel32.WaitForMultipleObjects.argtypes = [
48
+ wintypes.DWORD,
49
+ ctypes.POINTER(wintypes.HANDLE),
50
+ wintypes.BOOL,
51
+ wintypes.DWORD,
52
+ ]
53
+ _kernel32.WaitForMultipleObjects.restype = wintypes.DWORD
54
+
12
55
  DEFAULT_ACCENT_PALETTE = [
13
56
  "#99ebff",
14
57
  "#00ccff",
@@ -162,16 +205,72 @@ class AccentColorWatcher:
162
205
  def __init__(self, event:Event=None):
163
206
  self.event = event or Event()
164
207
  self.palette = self.getSystemAccentColor()
208
+ self._watch_thread: threading.Thread | None = None
209
+ self._stop_event_handle: int | None = None
165
210
 
166
211
  @staticmethod
167
212
  def getSystemAccentColor():
168
213
  try:
169
- with winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Accent") as key:
214
+ with winreg.OpenKey(winreg.HKEY_CURRENT_USER, ACCENT_REGISTRY_PATH) as key:
170
215
  p, _ = winreg.QueryValueEx(key, "AccentPalette")
171
216
  except OSError:
172
217
  return DEFAULT_ACCENT_PALETTE.copy()
173
218
  return [f"#{p[i]:02x}{p[i+1]:02x}{p[i+2]:02x}" for i in range(0,len(p),4)]
174
219
 
220
+ @staticmethod
221
+ def _create_event_handle():
222
+ handle = _kernel32.CreateEventW(None, False, False, None)
223
+ if not handle:
224
+ raise ctypes.WinError(ctypes.get_last_error())
225
+ return int(handle)
226
+
227
+ @staticmethod
228
+ def _close_handle(handle: int | None):
229
+ if handle:
230
+ _kernel32.CloseHandle(handle)
231
+
232
+ def _watch_loop(self, stop_event_handle: int):
233
+ change_event_handle = None
234
+ try:
235
+ with winreg.OpenKey(
236
+ winreg.HKEY_CURRENT_USER,
237
+ ACCENT_REGISTRY_PATH,
238
+ 0,
239
+ winreg.KEY_READ | winreg.KEY_NOTIFY,
240
+ ) as key:
241
+ change_event_handle = self._create_event_handle()
242
+ wait_handles = (wintypes.HANDLE * 2)(change_event_handle, stop_event_handle)
243
+ key_handle = wintypes.HKEY(int(key.handle))
244
+ while True:
245
+ result = _advapi32.RegNotifyChangeKeyValue(
246
+ key_handle,
247
+ False,
248
+ REG_NOTIFY_CHANGE_LAST_SET,
249
+ wintypes.HANDLE(change_event_handle),
250
+ True,
251
+ )
252
+ if result != 0:
253
+ logger.debug("Accent watcher registry notification failed: %s", result)
254
+ break
255
+
256
+ wait_result = _kernel32.WaitForMultipleObjects(2, wait_handles, False, INFINITE)
257
+ if wait_result == WAIT_OBJECT_0:
258
+ self.refresh()
259
+ continue
260
+ if wait_result == WAIT_OBJECT_0 + 1:
261
+ break
262
+
263
+ logger.debug("Accent watcher wait failed: %s", wait_result)
264
+ break
265
+ except Exception:
266
+ logger.debug("Accent watcher stopped unexpectedly", exc_info=True)
267
+ finally:
268
+ self._close_handle(change_event_handle)
269
+ self._close_handle(stop_event_handle)
270
+ if self._stop_event_handle == stop_event_handle:
271
+ self._stop_event_handle = None
272
+ self._watch_thread = None
273
+
175
274
  def refresh(self):
176
275
  if self.palette != (color := self.getSystemAccentColor()):
177
276
  self.palette = color
@@ -179,4 +278,24 @@ class AccentColorWatcher:
179
278
 
180
279
  def start(self):
181
280
  self.refresh()
281
+ if self._watch_thread and self._watch_thread.is_alive():
282
+ return
283
+
284
+ try:
285
+ self._stop_event_handle = self._create_event_handle()
286
+ except Exception:
287
+ logger.debug("Failed to start accent watcher", exc_info=True)
288
+ return
289
+
290
+ self._watch_thread = threading.Thread(
291
+ target=self._watch_loop,
292
+ args=(self._stop_event_handle,),
293
+ daemon=True,
294
+ name="AccentColorWatcher",
295
+ )
296
+ self._watch_thread.start()
182
297
  logger.debug("Accent watcher initialized")
298
+
299
+ def stop(self):
300
+ if self._stop_event_handle:
301
+ _kernel32.SetEvent(wintypes.HANDLE(self._stop_event_handle))