├── .prettierignore
├── example
├── react-vite
│ ├── .gitignore
│ ├── src
│ │ ├── vite-env.d.ts
│ │ ├── App.tsx
│ │ ├── main.tsx
│ │ └── index.css
│ ├── _gitignore
│ ├── vite.config.ts
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ ├── deploy-vercel.js
│ ├── public
│ │ └── favicon.svg
│ └── CHANGELOG.md
├── vanilla-ts
│ ├── src
│ │ ├── vite-env.d.ts
│ │ ├── style.css
│ │ └── main.ts
│ ├── .gitignore
│ ├── index.html
│ ├── package.json
│ ├── tsconfig.json
│ ├── favicon.svg
│ └── CHANGELOG.md
├── react-next
│ ├── next.config.js
│ ├── pages
│ │ ├── index.tsx
│ │ └── _app.tsx
│ ├── next-env.d.ts
│ ├── styles
│ │ └── globals.css
│ ├── tsconfig.json
│ ├── README.md
│ ├── package.json
│ └── CHANGELOG.md
└── vue-vite
│ ├── postcss.config.cjs
│ ├── src
│ ├── main.ts
│ ├── vite-env.d.ts
│ ├── App.vue
│ ├── components
│ │ ├── Ready.vue
│ │ ├── Fallback.vue
│ │ └── Button.vue
│ ├── style.css
│ ├── hooks
│ │ └── useNativeState.ts
│ └── Home.vue
│ ├── tsconfig.node.json
│ ├── vite.config.ts
│ ├── tailwind.config.cjs
│ ├── .gitignore
│ ├── index.html
│ ├── tsconfig.json
│ ├── package.json
│ ├── README.md
│ ├── public
│ └── vite.svg
│ └── CHANGELOG.md
├── .npmrc
├── pnpm-workspace.yaml
├── packages
├── debug-tools
│ ├── src
│ │ ├── vite-env.d.ts
│ │ ├── hooks
│ │ │ ├── index.tsx
│ │ │ ├── theme.tsx
│ │ │ └── request.tsx
│ │ ├── api
│ │ │ ├── common.ts
│ │ │ └── preview.ts
│ │ ├── main.tsx
│ │ ├── components
│ │ │ ├── Space.tsx
│ │ │ ├── Inspector.tsx
│ │ │ ├── Debuggable.tsx
│ │ │ ├── SiteInfo.tsx
│ │ │ ├── Tooltip.tsx
│ │ │ ├── Modal.tsx
│ │ │ └── CopyableScript.tsx
│ │ ├── shim.d.ts
│ │ ├── utils
│ │ │ └── index.ts
│ │ ├── server.ts
│ │ └── app.tsx
│ ├── bin.js
│ ├── .gitignore
│ ├── server
│ │ └── package.json
│ ├── index.html
│ ├── README.md
│ ├── tsconfig.json
│ ├── vite.config.ts
│ ├── CHANGELOG.md
│ └── package.json
├── lib
│ ├── src
│ │ ├── index.ts
│ │ ├── utils.ts
│ │ ├── constant.ts
│ │ └── debug.ts
│ ├── debug
│ │ └── package.json
│ ├── README.md
│ ├── package.json
│ └── CHANGELOG.md
├── create
│ ├── bin.js
│ ├── README.md
│ ├── package.json
│ ├── CHANGELOG.md
│ └── src
│ │ ├── utils.ts
│ │ └── index.ts
├── debug
│ ├── bin.js
│ ├── src
│ │ ├── mincud
│ │ │ ├── commands
│ │ │ │ ├── index.ts
│ │ │ │ ├── simulator.ts
│ │ │ │ ├── adb.ts
│ │ │ │ ├── incu.ts
│ │ │ │ └── vscode.ts
│ │ │ ├── StringMatcher.ts
│ │ │ ├── server.ts
│ │ │ ├── logToConsole.ts
│ │ │ ├── client.ts
│ │ │ └── openBrowser.ts
│ │ └── index.ts
│ ├── mincud
│ │ └── cli
│ │ │ └── package.json
│ ├── package.json
│ ├── README.md
│ └── CHANGELOG.md
├── ui
│ ├── src
│ │ ├── orientation.ts
│ │ ├── toast.ts
│ │ ├── back-press.ts
│ │ └── index.ts
│ ├── README.md
│ ├── package.json
│ └── CHANGELOG.md
├── demos
│ └── react-demo-shared
│ │ ├── src
│ │ ├── index.ts
│ │ ├── mincu-bench.ts
│ │ ├── Fallback.tsx
│ │ ├── Button.tsx
│ │ └── Modal.tsx
│ │ ├── tsconfig.json
│ │ ├── package.json
│ │ └── CHANGELOG.md
├── react
│ ├── src
│ │ ├── index.ts
│ │ └── components
│ │ │ ├── Ready.tsx
│ │ │ ├── Fallback.tsx
│ │ │ └── ReadySSR.tsx
│ ├── README.md
│ ├── package.json
│ └── CHANGELOG.md
├── hooks
│ ├── src
│ │ ├── index.ts
│ │ ├── useAppReady.ts
│ │ ├── useSafeArea.ts
│ │ ├── useNativeState.ts
│ │ └── useReady.ts
│ ├── README.md
│ ├── package.json
│ └── CHANGELOG.md
├── core
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ ├── channel.ts
│ │ ├── types
│ │ │ ├── ncuos.ts
│ │ │ └── rn
│ │ │ │ ├── orientation.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── net_info.ts
│ │ │ │ └── clipboard.ts
│ │ ├── interface.ts
│ │ └── index.ts
│ └── CHANGELOG.md
├── data
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ ├── storage.ts
│ │ └── index.ts
│ └── CHANGELOG.md
├── event
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ └── CHANGELOG.md
├── network
│ ├── README.md
│ ├── package.json
│ ├── CHANGELOG.md
│ └── src
│ │ └── index.ts
└── vanilla
│ ├── README.md
│ ├── package.json
│ ├── src
│ ├── utils.ts
│ └── index.ts
│ └── CHANGELOG.md
├── .eslintignore
├── .prettierrc
├── babel.config.js
├── tests
└── run_example_scripts.mjs
├── .eslintrc.js
├── lerna.json
├── CONTRIBUTING.md
├── tsconfig.json
├── .gitignore
├── package.json
└── README.md
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
--------------------------------------------------------------------------------
/example/react-vite/.gitignore:
--------------------------------------------------------------------------------
1 | .vercel
2 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | auto-install-peers=true
2 | strict-peer-dependencies=false
--------------------------------------------------------------------------------
/example/react-vite/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/example/vanilla-ts/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'packages/**'
3 | - 'example/**'
4 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/packages/lib/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './constant'
2 | export * from './utils'
3 |
--------------------------------------------------------------------------------
/example/vanilla-ts/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 | dist-ssr
5 | *.local
--------------------------------------------------------------------------------
/packages/create/bin.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict'
3 | require('create-mincu')
4 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist
2 | example
3 | node_modules
4 | .eslintrc.js
5 | packages/debug-tools
6 | tests
--------------------------------------------------------------------------------
/example/react-vite/_gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 | dist-ssr
5 | *.local
6 |
--------------------------------------------------------------------------------
/packages/debug-tools/bin.js:
--------------------------------------------------------------------------------
1 | const server = require('./server')
2 |
3 | server.startDevTool()
4 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/hooks/index.tsx:
--------------------------------------------------------------------------------
1 | export * from './theme'
2 | export * from './request'
3 |
--------------------------------------------------------------------------------
/packages/debug-tools/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 | dist-ssr
5 | output
6 | *.local
7 |
--------------------------------------------------------------------------------
/packages/debug/bin.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict'
3 | require('v8-compile-cache')
4 | require('./mincud/cli').startCli()
5 |
--------------------------------------------------------------------------------
/example/react-next/next.config.js:
--------------------------------------------------------------------------------
1 | const withPreconstruct = require("@preconstruct/next");
2 |
3 | module.exports = withPreconstruct();
--------------------------------------------------------------------------------
/packages/lib/debug/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "main": "dist/mincu-lib-debug.cjs.js",
3 | "module": "dist/mincu-lib-debug.esm.js"
4 | }
5 |
--------------------------------------------------------------------------------
/example/vue-vite/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/packages/lib/src/utils.ts:
--------------------------------------------------------------------------------
1 | export const noop = () => {}
2 | export const _window = typeof window == 'undefined' ? global : (window as any)
3 |
--------------------------------------------------------------------------------
/packages/debug-tools/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-debug-tools-server",
3 | "main": "dist/mincu-debug-tools-server.cjs.js"
4 | }
5 |
--------------------------------------------------------------------------------
/packages/debug/src/mincud/commands/index.ts:
--------------------------------------------------------------------------------
1 | export * from './incu'
2 | export * from './adb'
3 | export * from './simulator'
4 | export * from './vscode'
5 |
--------------------------------------------------------------------------------
/packages/ui/src/orientation.ts:
--------------------------------------------------------------------------------
1 | import mincuCore from 'mincu-core'
2 |
3 | export const orientation = mincuCore.makeProxyFromNativeFunc('Orientation')
4 |
--------------------------------------------------------------------------------
/example/vue-vite/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import './style.css'
3 | import App from './App.vue'
4 |
5 | createApp(App).mount('#app')
6 |
--------------------------------------------------------------------------------
/packages/debug/mincud/cli/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-debug-mincud-cli",
3 | "main": "dist/mincu-debug-mincud-cli.cjs.js",
4 | "module": "dist/mincu-debug-mincud-cli.esm.js"
5 | }
6 |
--------------------------------------------------------------------------------
/packages/demos/react-demo-shared/src/index.ts:
--------------------------------------------------------------------------------
1 | export { Fallback } from './Fallback'
2 | export { Demo } from './Demo'
3 | export { Button } from './Button'
4 | export * from './mincu-bench'
5 |
--------------------------------------------------------------------------------
/packages/react/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from 'mincu-vanilla'
2 | export * from 'mincu-hooks'
3 | export { ReadySSR } from './components/ReadySSR'
4 | export { Ready } from './components/Ready'
5 |
--------------------------------------------------------------------------------
/example/react-next/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import { Demo } from 'mincu-react-demo-shared';
2 |
3 | const App = () => {
4 | return (
5 |
6 | )
7 | }
8 |
9 | export default App
10 |
--------------------------------------------------------------------------------
/packages/hooks/src/index.ts:
--------------------------------------------------------------------------------
1 | export { default as useNativeState } from './useNativeState'
2 | export { default as useSafeArea } from './useSafeArea'
3 | export { default as useAppReady } from './useAppReady'
4 |
--------------------------------------------------------------------------------
/example/react-vite/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()]
7 | })
8 |
--------------------------------------------------------------------------------
/example/vue-vite/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | declare module '*.vue' {
4 | import type { DefineComponent } from 'vue'
5 | const component: DefineComponent<{}, {}, any>
6 | export default component
7 | }
8 |
--------------------------------------------------------------------------------
/example/react-next/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/example/vanilla-ts/src/style.css:
--------------------------------------------------------------------------------
1 | #app {
2 | font-family: Avenir, Helvetica, Arial, sans-serif;
3 | -webkit-font-smoothing: antialiased;
4 | -moz-osx-font-smoothing: grayscale;
5 | text-align: center;
6 | color: #2c3e50;
7 | margin-top: 60px;
8 | }
9 |
--------------------------------------------------------------------------------
/example/vue-vite/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "ESNext",
5 | "moduleResolution": "Node",
6 | "allowSyntheticDefaultImports": true
7 | },
8 | "include": ["vite.config.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "semi": false,
6 | "singleQuote": true,
7 | "jsxSingleQuote": false,
8 | "bracketSpacing": true,
9 | "arrowParens": "always",
10 | "printWidth": 80
11 | }
12 |
--------------------------------------------------------------------------------
/example/vue-vite/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [vue()],
7 | server: {
8 | port: 3000
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/packages/debug/src/mincud/commands/simulator.ts:
--------------------------------------------------------------------------------
1 | import execa from 'execa'
2 |
3 | export function openUrlSimulator(url: string) {
4 | try {
5 | return execa('xcrun', ['simctl', 'openurl', 'booted', url])
6 | } catch (e) {
7 | throw e
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/example/vue-vite/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: [
4 | "./index.html",
5 | "./src/**/*.{vue,js,ts,jsx,tsx}",
6 | ],
7 | theme: {
8 | extend: {},
9 | },
10 | plugins: [],
11 | }
12 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@babel/preset-typescript',
4 | [
5 | '@babel/preset-env',
6 | {
7 | targets: {
8 | node: '12',
9 | },
10 | },
11 | ],
12 | '@babel/preset-react'
13 | ]
14 | }
--------------------------------------------------------------------------------
/example/react-vite/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { Ready } from 'mincu-react'
2 | import { Demo, Fallback } from 'mincu-react-demo-shared';
3 |
4 | const App = () => {
5 | return (
6 | }>
7 |
8 |
9 | )
10 | }
11 |
12 | export default App
13 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/api/common.ts:
--------------------------------------------------------------------------------
1 | import { IncomingMessage, ServerResponse } from 'http'
2 |
3 | type Listeners = (req: IncomingMessage, res: ServerResponse) => void
4 |
5 | export const makeApi = (cb: Listeners) => {
6 | return (req: IncomingMessage, res: ServerResponse) => cb(req, res)
7 | }
8 |
--------------------------------------------------------------------------------
/packages/ui/README.md:
--------------------------------------------------------------------------------
1 | # mincu-ui
2 |
3 | 
4 |
5 | [Mincu - 南大家园 WEB JS API](https://github.com/ncuhome/mincu)
6 |
7 | ## Install
8 |
9 | ```cmd
10 | $ yarn add mincu-ui
11 | # or
12 | $ npm install mincu-ui
13 | ```
--------------------------------------------------------------------------------
/packages/lib/README.md:
--------------------------------------------------------------------------------
1 | # mincu-lib
2 |
3 | 
4 |
5 | [Mincu - 南大家园 WEB JS API](https://github.com/ncuhome/mincu)
6 |
7 | ## Install
8 |
9 | ```cmd
10 | $ yarn add mincu-lib
11 | # or
12 | $ npm install mincu-lib
13 | ```
--------------------------------------------------------------------------------
/example/vue-vite/src/App.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/packages/core/README.md:
--------------------------------------------------------------------------------
1 | # mincu-core
2 |
3 | 
4 |
5 | [Mincu - 南大家园 WEB JS API](https://github.com/ncuhome/mincu)
6 |
7 | ## Install
8 |
9 | ```cmd
10 | $ yarn add mincu-core
11 | # or
12 | $ npm install mincu-core
13 | ```
--------------------------------------------------------------------------------
/packages/data/README.md:
--------------------------------------------------------------------------------
1 | # mincu-data
2 |
3 | 
4 |
5 | [Mincu - 南大家园 WEB JS API](https://github.com/ncuhome/mincu)
6 |
7 | ## Install
8 |
9 | ```cmd
10 | $ yarn add mincu-data
11 | # or
12 | $ npm install mincu-data
13 | ```
--------------------------------------------------------------------------------
/example/react-next/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import '../styles/globals.css'
2 |
3 | import { ReadySSR } from "mincu-react"
4 | import { Fallback } from "mincu-react-demo-shared"
5 |
6 | export default function App({ Component, pageProps }) {
7 | return }>
8 | }
9 |
--------------------------------------------------------------------------------
/packages/event/README.md:
--------------------------------------------------------------------------------
1 | # mincu-event
2 |
3 | 
4 |
5 | [Mincu - 南大家园 WEB JS API](https://github.com/ncuhome/mincu)
6 |
7 | ## Install
8 |
9 | ```cmd
10 | $ yarn add mincu-event
11 | # or
12 | $ npm install mincu-event
13 | ```
--------------------------------------------------------------------------------
/packages/hooks/README.md:
--------------------------------------------------------------------------------
1 | # mincu-hooks
2 |
3 | 
4 |
5 | [Mincu - 南大家园 WEB JS API](https://github.com/ncuhome/mincu)
6 |
7 | ## Install
8 |
9 | ```cmd
10 | $ yarn add mincu-hooks
11 | # or
12 | $ npm install mincu-hooks
13 | ```
--------------------------------------------------------------------------------
/packages/react/README.md:
--------------------------------------------------------------------------------
1 | # mincu-react
2 |
3 | 
4 |
5 | [Mincu - 南大家园 WEB JS API](https://github.com/ncuhome/mincu)
6 |
7 | ## Install
8 |
9 | ```cmd
10 | $ yarn add mincu-react
11 | # or
12 | $ npm install mincu-react
13 | ```
--------------------------------------------------------------------------------
/packages/network/README.md:
--------------------------------------------------------------------------------
1 | # mincu-network
2 |
3 | 
4 |
5 | [Mincu - 南大家园 WEB JS API](https://github.com/ncuhome/mincu)
6 |
7 | ## Install
8 |
9 | ```cmd
10 | $ yarn add mincu-network
11 | # or
12 | $ npm install mincu-network
13 | ```
--------------------------------------------------------------------------------
/packages/vanilla/README.md:
--------------------------------------------------------------------------------
1 | # mincu-vanilla
2 |
3 | 
4 |
5 | [Mincu - 南大家园 WEB JS API](https://github.com/ncuhome/mincu)
6 |
7 | ## Install
8 |
9 | ```cmd
10 | $ yarn add mincu-vanilla
11 | # or
12 | $ npm install mincu-vanilla
13 | ```
--------------------------------------------------------------------------------
/tests/run_example_scripts.mjs:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env zx
2 |
3 | process.env.FORCE_COLOR=3
4 |
5 | const examplePath = path.join(__dirname, '..', 'example');
6 |
7 | const pkgs = await glob(`${examplePath}/*/package.json`);
8 |
9 | for (const pkg of pkgs) {
10 | const example = path.dirname(pkg)
11 | cd(example)
12 | await $`npm run build`
13 | }
14 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/main.tsx:
--------------------------------------------------------------------------------
1 | import 'virtual:uno.css'
2 | import '@unocss/reset/tailwind.css'
3 | import 'allotment/dist/style.css'
4 | import 'simplebar/src/simplebar.css'
5 |
6 | import React from 'react'
7 | import ReactDOM from 'react-dom/client'
8 | import { App } from './app'
9 |
10 | ReactDOM.createRoot(document.getElementById('app')!).render()
11 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: ['@typescript-eslint/eslint-plugin', 'prettier'],
3 | parser: '@typescript-eslint/parser',
4 | parserOptions: {
5 | project: './tsconfig.json',
6 | tsconfigRootDir: __dirname,
7 | ecmaVersion: 2018,
8 | sourceType: 'module',
9 | },
10 | rules: {
11 | 'prettier/prettier': 'error',
12 | },
13 | }
14 |
--------------------------------------------------------------------------------
/packages/hooks/src/useAppReady.ts:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import mincuCore from 'mincu-core'
3 | import useReady from './useReady'
4 |
5 | export default (reject = () => {}): boolean => {
6 | const [isReady, setIsReady] = useState(mincuCore.isReady && mincuCore.isApp)
7 |
8 | useReady(() => setIsReady(true), reject, [])
9 |
10 | return isReady
11 | }
12 |
--------------------------------------------------------------------------------
/packages/debug-tools/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Mincu Debug Tools
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/example/vue-vite/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/packages/hooks/src/useSafeArea.ts:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import { EdgeInsets } from 'mincu-core'
3 | import useReady from './useReady'
4 | import dataModule from 'mincu-data'
5 |
6 | export default () => {
7 | const [inset, setInset] = useState({} as EdgeInsets)
8 |
9 | useReady(() => {
10 | setInset(dataModule.inset)
11 | }, [])
12 |
13 | return inset
14 | }
15 |
--------------------------------------------------------------------------------
/example/react-vite/src/main.tsx:
--------------------------------------------------------------------------------
1 | import { StrictMode } from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import './index.css'
4 | import App from './App'
5 |
6 | import debug from 'mincu-debug'
7 |
8 | debug.connect()
9 |
10 | const rootElement = document.getElementById('root')
11 | const root = createRoot(rootElement!)
12 |
13 | root.render(
14 |
15 |
16 |
17 | )
18 |
--------------------------------------------------------------------------------
/packages/create/README.md:
--------------------------------------------------------------------------------
1 | # create-mincu
2 |
3 | [Mincu - 南大家园](https://github.com/ncuhome/mincu)
4 |
5 | ## Quick Start
6 |
7 | 快速创建 mincu 项目:
8 |
9 | ```sh
10 | # npm
11 | $ npm init mincu@latest
12 | # yarn
13 | $ yarn create mincu
14 | # pnpm
15 | $ pnpm create mincu
16 | # or
17 | $ npx create-mincu
18 | ```
19 |
20 | ## Thanks
21 |
22 | - [create-vite](https://github.com/vitejs/vite/tree/main/packages/create-vite)
23 |
--------------------------------------------------------------------------------
/example/vanilla-ts/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/example/react-vite/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/example/vue-vite/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite + Vue + TS
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/example/react-vite/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/example/react-next/styles/globals.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/example/vanilla-ts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "debug-module",
3 | "private": true,
4 | "version": "2.13.2",
5 | "scripts": {
6 | "start": "mincud npm run dev",
7 | "dev": "vite --host",
8 | "build": "vite build",
9 | "serve": "vite preview"
10 | },
11 | "devDependencies": {
12 | "typescript": "^4.7.4",
13 | "vite": "^3.0.4"
14 | },
15 | "dependencies": {
16 | "mincu-debug": "workspace:2.13.2"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/ui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-ui",
3 | "version": "2.13.2",
4 | "homepage": "https://github.com/ncuhome",
5 | "repository": {
6 | "type": "git",
7 | "url": "git@github.com:ncuhome/mincu.git"
8 | },
9 | "license": "MIT",
10 | "main": "dist/mincu-ui.cjs.js",
11 | "module": "dist/mincu-ui.esm.js",
12 | "files": [
13 | "dist"
14 | ],
15 | "dependencies": {
16 | "mincu-core": "workspace:2.13.2"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/demos/react-demo-shared/src/mincu-bench.ts:
--------------------------------------------------------------------------------
1 | import { mincu } from 'mincu-react'
2 | import { Bench } from 'tinybench'
3 |
4 | export const mincuBench = (times = 10) => {
5 | const bench = new Bench({ iterations: times })
6 |
7 | bench.add('handleShowHeader', async () => {
8 | await mincu.handleShowHeader(true)
9 | await mincu.handleShowHeader(false)
10 | await mincu.handleShowHeader(true)
11 | })
12 |
13 | return bench.run()
14 | }
15 |
--------------------------------------------------------------------------------
/packages/event/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-event",
3 | "version": "2.13.2",
4 | "homepage": "https://github.com/ncuhome",
5 | "repository": {
6 | "type": "git",
7 | "url": "git@github.com:ncuhome/mincu.git"
8 | },
9 | "license": "MIT",
10 | "main": "dist/mincu-event.cjs.js",
11 | "module": "dist/mincu-event.esm.js",
12 | "files": [
13 | "dist"
14 | ],
15 | "dependencies": {
16 | "mincu-core": "workspace:2.13.2"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/react/src/components/Ready.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react'
2 | import { useAppReady } from 'mincu-hooks'
3 | import { Fallback } from './Fallback'
4 |
5 | export interface Props {
6 | fallback?: React.ReactNode
7 | children?: React.ReactNode
8 | }
9 |
10 | export const Ready: FC = ({
11 | fallback = () as any,
12 | children,
13 | }) => {
14 | const isReady = useAppReady()
15 |
16 | return isReady ? children : fallback
17 | }
18 |
--------------------------------------------------------------------------------
/example/vue-vite/src/components/Ready.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/packages/core/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-core",
3 | "version": "2.13.2",
4 | "homepage": "https://github.com/ncuhome",
5 | "repository": {
6 | "type": "git",
7 | "url": "git@github.com:ncuhome/mincu.git"
8 | },
9 | "license": "MIT",
10 | "main": "dist/mincu-core.cjs.js",
11 | "module": "dist/mincu-core.esm.js",
12 | "files": [
13 | "dist"
14 | ],
15 | "dependencies": {
16 | "events": "^3.3.0",
17 | "mincu-lib": "workspace:2.13.2"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/debug-tools/README.md:
--------------------------------------------------------------------------------
1 | # mincu-debug-tools
2 |
3 | [](https://packagephobia.com/result?p=mincu-debug-tools)
4 |
5 | [Mincu - 南大家园 WEB JS API](https://github.com/ncuhome/mincu)
6 |
7 | Devtools for mincu-debug
8 |
9 | ## Install
10 |
11 | ```cmd
12 | $ yarn add mincu-debug-tools
13 | # or
14 | $ npm install mincu-debug-tools
15 | ```
16 |
17 | ## Thanks
18 |
19 | - [expo/expo-cli](https://github.com/expo/expo-cli)
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "packages": [
3 | "packages/*",
4 | "packages/demos/*",
5 | "example/*"
6 | ],
7 | "command": {
8 | "publish": {
9 | "conventionalCommits": true,
10 | "exact": true,
11 | "message": "chore: publish %s",
12 | "registry": "https://registry.npmjs.org/"
13 | },
14 | "version": {
15 | "conventionalCommits": true,
16 | "syncWorkspaceLock": true
17 | }
18 | },
19 | "version": "2.13.2",
20 | "npmClient": "pnpm"
21 | }
22 |
--------------------------------------------------------------------------------
/packages/data/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-data",
3 | "version": "2.13.2",
4 | "homepage": "https://github.com/ncuhome",
5 | "repository": {
6 | "type": "git",
7 | "url": "git@github.com:ncuhome/mincu.git"
8 | },
9 | "license": "MIT",
10 | "main": "dist/mincu-data.cjs.js",
11 | "module": "dist/mincu-data.esm.js",
12 | "files": [
13 | "dist"
14 | ],
15 | "dependencies": {
16 | "mincu-core": "workspace:2.13.2",
17 | "mincu-lib": "workspace:2.13.2"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/example/vue-vite/src/style.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | body {
6 | margin: 0;
7 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
8 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
9 | sans-serif;
10 | -webkit-font-smoothing: antialiased;
11 | -moz-osx-font-smoothing: grayscale;
12 | }
13 |
14 | code {
15 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
16 | monospace;
17 | }
18 |
--------------------------------------------------------------------------------
/example/vanilla-ts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "module": "ESNext",
5 | "lib": ["ESNext", "DOM"],
6 | "moduleResolution": "Node",
7 | "strict": false,
8 | "sourceMap": true,
9 | "resolveJsonModule": true,
10 | "esModuleInterop": true,
11 | "noEmit": true,
12 | "noUnusedLocals": true,
13 | "noUnusedParameters": true,
14 | "noImplicitReturns": true,
15 | "skipLibCheck": true,
16 | "baseUrl": "."
17 | },
18 | "include": ["./src"]
19 | }
20 |
--------------------------------------------------------------------------------
/packages/lib/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-lib",
3 | "version": "2.13.2",
4 | "homepage": "https://github.com/ncuhome",
5 | "repository": {
6 | "type": "git",
7 | "url": "git@github.com:ncuhome/mincu.git"
8 | },
9 | "license": "MIT",
10 | "main": "dist/mincu-lib.cjs.js",
11 | "module": "dist/mincu-lib.esm.js",
12 | "files": [
13 | "dist",
14 | "debug"
15 | ],
16 | "publishConfig": {
17 | "access": "public"
18 | },
19 | "preconstruct": {
20 | "entrypoints": [
21 | "index.ts",
22 | "debug.ts"
23 | ]
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-react",
3 | "version": "2.13.2",
4 | "homepage": "https://github.com/ncuhome",
5 | "repository": {
6 | "type": "git",
7 | "url": "git@github.com:ncuhome/mincu.git"
8 | },
9 | "license": "MIT",
10 | "main": "dist/mincu-react.cjs.js",
11 | "module": "dist/mincu-react.esm.js",
12 | "files": [
13 | "dist"
14 | ],
15 | "dependencies": {
16 | "mincu-hooks": "workspace:2.13.2",
17 | "mincu-vanilla": "workspace:2.13.2"
18 | },
19 | "peerDependencies": {
20 | "react": ">=17"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/components/Space.tsx:
--------------------------------------------------------------------------------
1 | import { FC } from 'react'
2 |
3 | interface Props {
4 | /**
5 | * @default 4
6 | */
7 | x?: number | string
8 | /**
9 | * @default 4
10 | */
11 | y?: number | string
12 | direction?: 'row' | 'column'
13 | }
14 |
15 | const Space: FC = ({ x = 4, y = 4, direction = 'column' }) => {
16 | return (
17 |
23 | )
24 | }
25 |
26 | export default Space
27 |
--------------------------------------------------------------------------------
/packages/network/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-network",
3 | "version": "2.13.2",
4 | "homepage": "https://github.com/ncuhome",
5 | "repository": {
6 | "type": "git",
7 | "url": "git@github.com:ncuhome/mincu.git"
8 | },
9 | "license": "MIT",
10 | "main": "dist/mincu-network.cjs.js",
11 | "module": "dist/mincu-network.esm.js",
12 | "files": [
13 | "dist"
14 | ],
15 | "dependencies": {
16 | "mincu-core": "workspace:2.13.2",
17 | "mincu-data": "workspace:2.13.2"
18 | },
19 | "devDependencies": {
20 | "axios": "^0.27.2"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/lib/src/constant.ts:
--------------------------------------------------------------------------------
1 | export const defaultUserData = {
2 | token: '',
3 | colorScheme: 'light',
4 | colors: {},
5 | inset: { top: 0, right: 0, bottom: 0, left: 0 },
6 | profile: {
7 | basicProfile: {
8 | app_avatar_url: '',
9 | department: '',
10 | department_id: '',
11 | head_pic_url: '',
12 | max_role_level: 0,
13 | message: '',
14 | name: '',
15 | status: 0,
16 | },
17 | entireProfile: {
18 | base_info: null,
19 | is_teacher: false,
20 | message: '',
21 | status: 0,
22 | },
23 | },
24 | }
25 |
--------------------------------------------------------------------------------
/packages/hooks/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-hooks",
3 | "version": "2.13.2",
4 | "homepage": "https://github.com/ncuhome",
5 | "repository": {
6 | "type": "git",
7 | "url": "git@github.com:ncuhome/mincu.git"
8 | },
9 | "license": "MIT",
10 | "main": "dist/mincu-hooks.cjs.js",
11 | "module": "dist/mincu-hooks.esm.js",
12 | "files": [
13 | "dist"
14 | ],
15 | "dependencies": {
16 | "lodash": "^4.17.21",
17 | "mincu-core": "workspace:2.13.2",
18 | "mincu-data": "workspace:2.13.2"
19 | },
20 | "peerDependencies": {
21 | "react": ">=17"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/vue-vite/src/hooks/useNativeState.ts:
--------------------------------------------------------------------------------
1 | import { ref, onBeforeUnmount, onMounted } from 'vue'
2 | import { States, mincuCore, dataModule } from 'mincu-vanilla'
3 |
4 | export default (key: T, defaultVal?: any) => {
5 | const state = ref(defaultVal)
6 |
7 | const handle = (res: States[T]) => {
8 | state.value = res
9 | }
10 |
11 | onMounted(() => {
12 | handle(dataModule?.[key] ?? {})
13 | mincuCore.listener(key, handle)
14 | })
15 |
16 | onBeforeUnmount(() => {
17 | mincuCore.remove(key, handle)
18 | })
19 |
20 | return state
21 | }
22 |
--------------------------------------------------------------------------------
/example/react-next/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": false,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true
17 | },
18 | "exclude": ["node_modules"],
19 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
20 | }
21 |
--------------------------------------------------------------------------------
/example/react-vite/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["./src"]
20 | }
21 |
--------------------------------------------------------------------------------
/packages/demos/react-demo-shared/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": false,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "moduleResolution": "Node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["./src"]
20 | }
21 |
--------------------------------------------------------------------------------
/example/vue-vite/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "module": "ESNext",
6 | "moduleResolution": "Node",
7 | "strict": true,
8 | "jsx": "preserve",
9 | "sourceMap": true,
10 | "resolveJsonModule": true,
11 | "isolatedModules": true,
12 | "esModuleInterop": true,
13 | "lib": ["ESNext", "DOM"],
14 | "skipLibCheck": true,
15 | "types": [
16 | "vite/client",
17 | ]
18 | },
19 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
20 | "references": [{ "path": "./tsconfig.node.json" }]
21 | }
22 |
--------------------------------------------------------------------------------
/packages/data/src/storage.ts:
--------------------------------------------------------------------------------
1 | import mincuCore from 'mincu-core'
2 |
3 | export class MincuStorage {
4 | async getItem(key: string) {
5 | return mincuCore.callPromise('Storage', 'getItem', [key])
6 | }
7 |
8 | async setItem(key: string, value: any) {
9 | return mincuCore.callPromise('Storage', 'setItem', [key, value])
10 | }
11 |
12 | async removeItem(key: string) {
13 | return this.remove(key)
14 | }
15 |
16 | async remove(key: string) {
17 | return mincuCore.callPromise('Storage', 'remove', [key])
18 | }
19 |
20 | async reset() {
21 | return mincuCore.callPromise('Storage', 'reset', null)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/packages/vanilla/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-vanilla",
3 | "version": "2.13.2",
4 | "homepage": "https://github.com/ncuhome",
5 | "repository": {
6 | "type": "git",
7 | "url": "git@github.com:ncuhome/mincu.git"
8 | },
9 | "license": "MIT",
10 | "main": "dist/mincu-vanilla.cjs.js",
11 | "module": "dist/mincu-vanilla.esm.js",
12 | "files": [
13 | "dist"
14 | ],
15 | "dependencies": {
16 | "mincu-core": "workspace:2.13.2",
17 | "mincu-data": "workspace:2.13.2",
18 | "mincu-event": "workspace:2.13.2",
19 | "mincu-network": "workspace:2.13.2",
20 | "mincu-ui": "workspace:2.13.2"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/example/react-next/README.md:
--------------------------------------------------------------------------------
1 | # Mincu React 模板
2 |
3 | 1. 目前没有发包,请自行 link 后再进行调试
4 | 2. 考虑将 lib/hooks 代码放在主包里
5 | 3. 之后使用 deeplink 在 app 端内调试
6 |
7 | ## Link 步骤
8 |
9 | ```shell
10 | # 1. mincu/
11 | yarn link
12 |
13 | # 2. mincu/example/react-next/
14 | yarn link mincu
15 |
16 | # 3. mincu/example/react-next/node_modules/react/
17 | yarn link
18 |
19 | # 4. mincu/
20 | yarn link react
21 | ```
22 |
23 | ## 如何调试
24 |
25 | [iOS 调试方法](https://github.com/react-native-webview/react-native-webview/blob/master/docs/Debugging.md#ios--safari)
26 |
27 | [Android 调试方法](https://github.com/react-native-webview/react-native-webview/blob/master/docs/Debugging.md#android--chrome)
--------------------------------------------------------------------------------
/example/vue-vite/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-vite",
3 | "private": true,
4 | "version": "2.13.2",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vue-tsc --noEmit && vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "mincu-vanilla": "workspace:2.13.2",
13 | "qrcode.vue": "^3.3.3",
14 | "vue": "^3.2.37"
15 | },
16 | "devDependencies": {
17 | "@vitejs/plugin-vue": "^3.0.1",
18 | "autoprefixer": "^10.4.8",
19 | "postcss": "^8.4.16",
20 | "tailwindcss": "^3.1.8",
21 | "typescript": "^4.7.4",
22 | "vite": "^3.0.4",
23 | "vue-tsc": "^0.39.5"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/react/src/components/Fallback.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | export const Fallback = () => (
4 |
30 | )
31 |
--------------------------------------------------------------------------------
/packages/react/src/components/ReadySSR.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC, Fragment, useEffect, useState } from 'react'
2 | import { useAppReady } from 'mincu-hooks'
3 | import { Fallback } from './Fallback'
4 |
5 | export interface Props {
6 | fallback?: React.ReactNode
7 | children?: React.ReactNode
8 | }
9 |
10 | export const ReadySSR: FC = ({
11 | fallback = () as any,
12 | children,
13 | }) => {
14 | const [isSSR, setIsSSR] = useState(true)
15 | const isReady = useAppReady()
16 |
17 | useEffect(() => {
18 | setIsSSR(false)
19 | }, [])
20 |
21 | const content = isReady ? children : fallback
22 |
23 | return {!isSSR && content}
24 | }
25 |
--------------------------------------------------------------------------------
/packages/debug-tools/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "allowJs": false,
7 | "skipLibCheck": true,
8 | "esModuleInterop": false,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "ESNext",
13 | "jsx": "preserve",
14 | "moduleResolution": "Node",
15 | "resolveJsonModule": true,
16 | "isolatedModules": true,
17 | "noEmit": true,
18 | "baseUrl": ".",
19 | "paths": {
20 | "@/*": ["src/*"]
21 | }
22 | },
23 | "include": ["src"]
24 | }
25 |
--------------------------------------------------------------------------------
/example/vanilla-ts/src/main.ts:
--------------------------------------------------------------------------------
1 | import './style.css'
2 |
3 | if (import.meta.env.DEV) {
4 | // only enables it in DEV mode
5 | import('mincu-debug').then(({ default: debugModule }) => {
6 | debugModule.applyConsole()
7 | })
8 | }
9 |
10 | const fakePromise = () => new Promise((_, reject) => {
11 | reject(new Error('fake error'))
12 | })
13 |
14 | const a = async () => {
15 | const res = await fakePromise()
16 | console.log(res)
17 | }
18 |
19 | setTimeout(() => {
20 | a()
21 | }, 1000)
22 |
23 | const app = document.querySelector('#app')!
24 |
25 | app.innerHTML = `
26 | Hello Vite!
27 | Documentation
28 | `
29 |
--------------------------------------------------------------------------------
/packages/demos/react-demo-shared/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-react-demo-shared",
3 | "version": "2.13.2",
4 | "main": "dist/mincu-react-demo-shared.cjs.js",
5 | "module": "dist/mincu-react-demo-shared.esm.js",
6 | "dependencies": {
7 | "@headlessui/react": "^1.6.5",
8 | "axios": "^0.27.2",
9 | "mincu-react": "workspace:*",
10 | "qrcode.react": "^3.1.0",
11 | "tinybench": "^2.0.9",
12 | "twind": "^0.16.17"
13 | },
14 | "peerDependencies": {
15 | "react": ">=17"
16 | },
17 | "devDependencies": {
18 | "@types/react": "^18.0.17",
19 | "@types/react-dom": "^18.0.6",
20 | "@vitejs/plugin-react": "^2.0.0",
21 | "typescript": "^4.7.4",
22 | "vite": "^3.0.4"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/packages/hooks/src/useNativeState.ts:
--------------------------------------------------------------------------------
1 | import { useState, useCallback } from 'react'
2 | import { States } from 'mincu-core'
3 | import mincuCore from 'mincu-core'
4 | import dataModule from 'mincu-data'
5 | import useReady from './useReady'
6 |
7 | /**
8 | * 返回 app 的状态
9 | */
10 | export default (key: T): States[T] => {
11 | const [value, setValue] = useState({})
12 |
13 | const handle = useCallback((res: States[T]) => {
14 | setValue(res)
15 | }, [])
16 |
17 | useReady(() => {
18 | setValue(dataModule?.[key] ?? {})
19 | mincuCore.listener(key, handle)
20 |
21 | return () => {
22 | mincuCore.remove(key, handle)
23 | }
24 | }, [])
25 |
26 | return value
27 | }
28 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/components/Inspector.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC, useRef, useCallback } from 'react'
2 | import { DebugTarget } from '@/shim'
3 | import { chiiFrontUrl } from '@/utils'
4 | import { useThemeChange } from '@/hooks'
5 |
6 | const Inspector: FC<{
7 | data: DebugTarget
8 | }> = ({ data }) => {
9 | const ref = useRef(null)
10 |
11 | useThemeChange(() => {
12 | if (ref.current) {
13 | ref.current.src = chiiFrontUrl(data.id, data.id)
14 | }
15 | })
16 |
17 | const getUrl = useCallback(() => {
18 | return chiiFrontUrl(data.id, data.id)
19 | }, [data.id])
20 |
21 | return
22 | }
23 |
24 | export default Inspector
25 |
--------------------------------------------------------------------------------
/packages/hooks/src/useReady.ts:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react'
2 | import isFunction from 'lodash/isFunction'
3 | import mincuCore from 'mincu-core'
4 |
5 | function useIsReady(resolve: () => void, deps?: any[]): void
6 | function useIsReady(resolve: () => void, reject: () => void, deps?: any[]): void
7 |
8 | function useIsReady(...args: any[]) {
9 | const [resolve, rejectOrDeps, deps] = args
10 | let _deps: any[]
11 |
12 | const hasReject = isFunction(rejectOrDeps)
13 |
14 | if (hasReject) {
15 | _deps = deps
16 | } else {
17 | _deps = rejectOrDeps
18 | }
19 |
20 | useEffect(() => {
21 | mincuCore.initial(resolve, hasReject ? rejectOrDeps : undefined)
22 | }, _deps)
23 | }
24 |
25 | export default useIsReady
26 |
--------------------------------------------------------------------------------
/packages/create/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "create-mincu",
3 | "version": "2.13.2",
4 | "homepage": "https://github.com/ncuhome",
5 | "repository": {
6 | "type": "git",
7 | "url": "git@github.com:ncuhome/mincu.git"
8 | },
9 | "license": "MIT",
10 | "main": "dist/create-mincu.cjs.js",
11 | "module": "dist/create-mincu.esm.js",
12 | "bin": {
13 | "create-mincu": "./bin.js"
14 | },
15 | "files": [
16 | "dist",
17 | "./bin.js"
18 | ],
19 | "dependencies": {
20 | "fs-extra": "^10.1.0",
21 | "gdl": "^1.5.0",
22 | "kolorist": "^1.5.1",
23 | "meow": "^10.1.2",
24 | "minimist": "^1.2.6",
25 | "prompts": "^2.4.2"
26 | },
27 | "devDependencies": {
28 | "@types/fs-extra": "^9.0.13"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/hooks/theme.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from 'react'
2 | import { useMedia } from 'react-use'
3 | import { setThemeClass } from '../utils'
4 |
5 | export const useThemeDark = () => {
6 | const isDark = useMedia('(prefers-color-scheme: dark)')
7 | return isDark
8 | }
9 |
10 | export const useTheme = () => {
11 | const isDark = useThemeDark()
12 | return isDark ? 'dark' : 'light'
13 | }
14 |
15 | export const useThemeWatcher = () => {
16 | const isDark = useThemeDark()
17 | useEffect(() => {
18 | setThemeClass(isDark)
19 | }, [isDark])
20 | }
21 |
22 | export const useThemeChange = (cb: (isDark: boolean) => void) => {
23 | const isDark = useThemeDark()
24 | useEffect(() => {
25 | cb(isDark)
26 | }, [isDark])
27 | }
28 |
--------------------------------------------------------------------------------
/example/vue-vite/src/components/Fallback.vue:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
请使用南大家园扫描以下二维码,即刻预览 🚀
11 |
12 |
13 |
14 | 还没有安装南大家园?
15 |
20 | 前往下载
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/packages/core/src/channel.ts:
--------------------------------------------------------------------------------
1 | import { EventEmitter } from 'events'
2 | import { _window } from 'mincu-lib'
3 |
4 | type Message = {
5 | key: number
6 | status: 'success' | 'failed'
7 | data: any
8 | }
9 |
10 | export type EventMap = {
11 | [key: number]: {
12 | success: any
13 | failed: any
14 | }
15 | }
16 |
17 | export const channelGenerator = (eventMap: EventMap) => {
18 | if (_window === 'undefined') return
19 |
20 | _window.RNMessageChannel = new EventEmitter()
21 |
22 | // 设置接受发送到客户端方法所返回的数值的监听器
23 | _window.RNMessageChannel.on('call', (message: Message) => {
24 | const { key, status, data } = message ?? {}
25 |
26 | const { success, failed } = eventMap[key]
27 |
28 | if (status === 'success') {
29 | success(data)
30 | } else {
31 | failed(data)
32 | }
33 | })
34 | }
35 |
--------------------------------------------------------------------------------
/packages/ui/src/toast.ts:
--------------------------------------------------------------------------------
1 | import mincuCore from 'mincu-core'
2 |
3 | export const toast = {
4 | info: (title: string, during: number = 1) => {
5 | return mincuCore.callPromise('Toast', 'info', [title, during])
6 | },
7 |
8 | loading: async (title: string, during: number = 1) => {
9 | const key = await mincuCore.callPromise('Toast', 'loading', [title, during])
10 | return () => {
11 | toast.remove(key)
12 | }
13 | },
14 |
15 | success: (title: string, during: number = 1) => {
16 | return mincuCore.callPromise('Toast', 'success', [title, during])
17 | },
18 |
19 | fail: (title: string, during: number = 1) => {
20 | return mincuCore.callPromise('Toast', 'fail', [title, during])
21 | },
22 |
23 | remove: (key: number) => {
24 | return mincuCore.callPromise('Portal', 'remove', [key])
25 | },
26 | }
27 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/shim.d.ts:
--------------------------------------------------------------------------------
1 | import type { AttributifyAttributes } from '@unocss/preset-attributify'
2 |
3 | declare module 'react' {
4 | interface HTMLAttributes extends AttributifyAttributes {}
5 | }
6 |
7 | import type { getLinkPreview } from 'link-preview-js'
8 |
9 | type SitePreview = Partial<{
10 | url: string
11 | title: string
12 | siteName: string | undefined
13 | description: string | undefined
14 | mediaType: string
15 | contentType: string | undefined
16 | images: string[]
17 | videos: {
18 | url: string | undefined
19 | secureUrl: string | null | undefined
20 | type: string | null | undefined
21 | width: string | undefined
22 | height: string | undefined
23 | }[]
24 | favicons: string[]
25 | }>
26 |
27 | type DebugTarget = {
28 | url: string
29 | id: string
30 | title: string
31 | }
32 |
--------------------------------------------------------------------------------
/example/react-vite/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vite-react-typescript-starter",
3 | "version": "2.13.2",
4 | "private": true,
5 | "scripts": {
6 | "build": "vite build",
7 | "dev": "vite --host",
8 | "preview": "vite preview",
9 | "start": "mincud npm run dev",
10 | "deploy:vercel": "node deploy-vercel.js"
11 | },
12 | "dependencies": {
13 | "mincu-react": "workspace:2.13.2",
14 | "mincu-react-demo-shared": "workspace:2.13.2",
15 | "react": "^18.2.0",
16 | "react-dom": "^18.2.0",
17 | "react-router-dom": "6.3.0"
18 | },
19 | "devDependencies": {
20 | "@types/react": "^18.0.17",
21 | "@types/react-dom": "^18.0.6",
22 | "@vitejs/plugin-react": "^2.0.0",
23 | "lodash": "^4.17.21",
24 | "mincu-debug": "workspace:2.13.2",
25 | "typescript": "^4.7.4",
26 | "vite": "^3.0.4"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/example/react-next/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "incu-react-next-example",
3 | "version": "2.13.2",
4 | "private": true,
5 | "license": "MIT",
6 | "scripts": {
7 | "build": "next build --no-lint",
8 | "dev": "next dev",
9 | "export": "next build && next export",
10 | "start": "next start"
11 | },
12 | "dependencies": {
13 | "mincu-react": "workspace:2.13.2",
14 | "mincu-react-demo-shared": "workspace:2.13.2",
15 | "react": "^18.2.0",
16 | "react-dom": "^18.2.0"
17 | },
18 | "devDependencies": {
19 | "@babel/core": "^7.18.10",
20 | "@preconstruct/next": "^4.0.0",
21 | "@types/node": "^18.6.4",
22 | "@types/prop-types": "^15.7.5",
23 | "@types/react": "^18.0.16",
24 | "next": "^12.2.2",
25 | "typescript": "^4.7.4"
26 | },
27 | "peerDependencies": {
28 | "@babel/core": "^7.18.10"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/packages/vanilla/src/utils.ts:
--------------------------------------------------------------------------------
1 | export const toObj = (proto) => {
2 | let jsoned = {}
3 | let toConvert = proto
4 | Object.getOwnPropertyNames(toConvert).forEach((prop) => {
5 | const val = toConvert[prop]
6 | // don't include those
7 | if (prop === 'toJSON' || prop === 'constructor') {
8 | return
9 | }
10 | if (typeof val === 'function') {
11 | jsoned[prop] = val.bind(jsoned)
12 | return
13 | }
14 | jsoned[prop] = val
15 | })
16 |
17 | const inherited = Object.getPrototypeOf(toConvert)
18 | if (inherited !== null) {
19 | Object.keys(toObj(inherited)).forEach((key) => {
20 | if (!!jsoned[key] || key === 'constructor' || key === 'toJSON') return
21 | if (typeof inherited[key] === 'function') {
22 | jsoned[key] = inherited[key].bind(jsoned)
23 | return
24 | }
25 | jsoned[key] = inherited[key]
26 | })
27 | }
28 | return jsoned
29 | }
30 |
--------------------------------------------------------------------------------
/packages/debug/src/mincud/commands/adb.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @reference https://github.com/expo/expo-cli/blob/master/packages/xdl/src/Android.ts
3 | */
4 |
5 | import execa from 'execa'
6 |
7 | const whichADB = () => {
8 | if (process.env.ANDROID_HOME) {
9 | return `${process.env.ANDROID_HOME}/platform-tools/adb`
10 | }
11 | return 'adb'
12 | }
13 |
14 | export const getAdbOutputAsync = (args: string[]) => {
15 | const adb = whichADB()
16 | try {
17 | return execa(adb, args)
18 | } catch (e) {
19 | throw e
20 | }
21 | }
22 |
23 | export const openUrlAdb = async (url: string) => {
24 | const args = [
25 | 'shell',
26 | 'am',
27 | 'start',
28 | '-a',
29 | 'android.intent.action.VIEW',
30 | '-d',
31 | url,
32 | ]
33 | try {
34 | const success = await getAdbOutputAsync(args)
35 | return !!success
36 | } catch (e: any) {
37 | console.error(e)
38 | return false
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/hooks/request.tsx:
--------------------------------------------------------------------------------
1 | import useSWR, { SWRConfiguration } from 'swr'
2 | import redaxios, { Response } from 'redaxios'
3 | import { API_HOST, CHII_URL } from '../utils'
4 | import { DebugTarget } from '@/shim'
5 |
6 | export const useTargets = (config?: SWRConfiguration) => {
7 | const { data, error, mutate } = useSWR>(
8 | `${CHII_URL}/targets`,
9 | redaxios.get,
10 | config
11 | )
12 |
13 | return {
14 | targets: data?.data || [],
15 | isLoading: !error && !data,
16 | isError: error,
17 | mutate,
18 | }
19 | }
20 |
21 | export const useIp = (config?: SWRConfiguration) => {
22 | const { data, error, mutate } = useSWR>(
23 | `${API_HOST}/ip`,
24 | redaxios.get,
25 | config
26 | )
27 |
28 | return {
29 | ip: data?.data || 'localhost',
30 | isLoading: !error && !data,
31 | isError: error,
32 | mutate,
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/vanilla/src/index.ts:
--------------------------------------------------------------------------------
1 | import mincuCore, { MincuCoreBase } from 'mincu-core'
2 | import dataModule, { DataModule } from 'mincu-data'
3 | import eventModule, { EventModule } from 'mincu-event'
4 | import networkModule, { NetWorkModule } from 'mincu-network'
5 | import uiModule, { UIModule } from 'mincu-ui'
6 | import { toObj } from './utils'
7 |
8 | export { mincuCore, dataModule, eventModule, networkModule, uiModule }
9 | export type {
10 | States,
11 | INativeFuncs,
12 | ShareConfig,
13 | NavConfig,
14 | AppData,
15 | EdgeInsets,
16 | ColorSchemeName,
17 | } from 'mincu-core'
18 |
19 | export interface Mincu
20 | extends MincuCoreBase,
21 | DataModule,
22 | EventModule,
23 | NetWorkModule,
24 | UIModule {}
25 |
26 | export const mincu = Object.assign(
27 | {},
28 | toObj(eventModule),
29 | toObj(dataModule),
30 | toObj(uiModule),
31 | toObj(networkModule),
32 | toObj(mincuCore)
33 | ) as Mincu
34 |
--------------------------------------------------------------------------------
/packages/debug/src/mincud/commands/incu.ts:
--------------------------------------------------------------------------------
1 | import { openUrlSimulator } from './simulator'
2 | import { openUrlAdb } from './adb'
3 |
4 | export const iNCUScheme = (postfix: string) => `incu://${postfix}`
5 |
6 | export const iNCUWebViewScheme = (url: string) =>
7 | iNCUScheme(`Webview?url=${url}`)
8 |
9 | const openUrls = {
10 | android: openUrlAdb,
11 | ios: openUrlSimulator,
12 | }
13 |
14 | export type Platform = 'android' | 'ios'
15 |
16 | /**
17 | * open url in iNCU Webview
18 | * @param url
19 | * @param platform 'android' | 'ios'
20 | * @returns boolean
21 | */
22 | export const openUrl = async (url: string, platform: Platform) => {
23 | try {
24 | const openUrl = openUrls[platform]
25 | if (!openUrl) {
26 | throw new Error(`platform ${platform} not supported`)
27 | }
28 | await openUrl(iNCUWebViewScheme(url))
29 | return true
30 | } catch (e: any) {
31 | console.error(e.stderr ?? e)
32 | return false
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/packages/demos/react-demo-shared/src/Fallback.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { QRCodeSVG } from 'qrcode.react'
3 | import { tw } from 'twind'
4 |
5 | const getPreviewUrl = () => {
6 | return location.href + '?devSecret=iNCUDeveloper++'
7 | }
8 |
9 | export const Fallback: React.FC = () => (
10 |
32 | )
33 |
--------------------------------------------------------------------------------
/packages/core/src/types/ncuos.ts:
--------------------------------------------------------------------------------
1 | export interface Base_info {
2 | csd: Csd
3 | csrq: string
4 | dzyx: string
5 | gb: Gb
6 | jg: Jg
7 | jhkh: string
8 | mz: Mz
9 | pyfs: Pyf
10 | qq: string
11 | qsh: string
12 | rxny: string
13 | sfzh: string
14 | xb: Xb
15 | xh: string
16 | xm: string
17 | xslb: Xslb
18 | xx: Xx
19 | yddh: string
20 | zzmm: Zzmm
21 | }
22 |
23 | interface Csd {
24 | dm: string
25 | mc: string
26 | }
27 |
28 | interface Gb {
29 | dm: string
30 | mc: string
31 | }
32 |
33 | interface Jg {
34 | dm: string
35 | mc: string
36 | }
37 |
38 | interface Mz {
39 | dm: string
40 | mc: string
41 | }
42 |
43 | interface Pyf {
44 | dm: string
45 | mc: string
46 | }
47 |
48 | interface Xb {
49 | dm: string
50 | mc: string
51 | }
52 |
53 | interface Xslb {
54 | dm: string
55 | mc: string
56 | }
57 |
58 | interface Xx {
59 | dm: string
60 | mc: string
61 | }
62 |
63 | interface Zzmm {
64 | dm: string
65 | mc: string
66 | }
67 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # mincu 贡献指南
2 |
3 | mincu 的项目结构为 monorepo,使用 pnpm workspaces + lerna lite 管理(之前为 yarn workspaces + lerna)。在开发之前,你需要先安装 [pnpm](https://pnpm.io/installation)
4 |
5 | ## 项目初始化
6 |
7 | ```cmd
8 | $ git clone https://github.com/ncuhome/mincu # or clone your fork
9 | $ cd mincu
10 | $ pnpm i
11 | $ pnpm dev
12 |
13 | # then start coding in packages/*
14 | ```
15 |
16 | ## 如何调试 debug, debug-tools
17 |
18 | ```cmd
19 | $ pnpm dev
20 | $ pnpm dev:debug-tools
21 | # then start coding in packages/debug or packages/debug-tools
22 | ```
23 |
24 | ## 运行示例
25 |
26 | ```cmd
27 | # example/vanilla-ts
28 | $ pnpm start
29 | ```
30 |
31 | 其他示例见 [example](./example),也可参考 [使用到的项目](#使用到的项目)
32 |
33 | ## 添加依赖
34 |
35 | 根目录下添加:
36 |
37 | ```cmd
38 | pnpm add -DW
39 | ```
40 |
41 | 某个 packages 下添加:
42 |
43 | ```cmd
44 | pnpm --filter add
45 | ```
46 |
47 | ## 发版(需要 NPM 账号权限)
48 |
49 | 更新版本号并发布到 npm
50 |
51 | ```cmd
52 | pnpm release #--dry-run
53 | ```
54 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES6",
4 | "lib": [
5 | "es2016",
6 | "dom"
7 | ],
8 | "moduleResolution": "node",
9 | "pretty": true,
10 | "declaration": true,
11 | "allowSyntheticDefaultImports": true,
12 | "esModuleInterop": true,
13 | "noImplicitAny": false,
14 | "experimentalDecorators": true,
15 | "allowJs": true,
16 | "sourceMap": true,
17 | "strict": false,
18 | "alwaysStrict": true,
19 | "strictNullChecks": false,
20 | "noUnusedLocals": true,
21 | "noUnusedParameters": true,
22 | "importHelpers": true,
23 | "skipLibCheck": true,
24 | "jsx": "preserve",
25 | "baseUrl": ".",
26 | "paths": {
27 | "mincu-*": ["./packages/*/src"]
28 | },
29 | "isolatedModules": true,
30 | "noEmit": true
31 | },
32 | "exclude": [
33 | "node_modules",
34 | "**/__tests__/*",
35 | "example",
36 | "**/dist",
37 | "**/output",
38 | "packages/debug-tools"
39 | ]
40 | }
--------------------------------------------------------------------------------
/packages/debug-tools/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 | import path from 'path'
4 | import Unocss from 'unocss/vite'
5 | import presetUno from '@unocss/preset-uno'
6 | import transformerDirective from '@unocss/transformer-directives'
7 | import presetIcons from '@unocss/preset-icons'
8 |
9 | export default defineConfig({
10 | plugins: [
11 | Unocss({
12 | presets: [
13 | presetUno({}),
14 | presetIcons({
15 | extraProperties: {
16 | display: 'inline-block',
17 | 'vertical-align': 'middle',
18 | // ...
19 | },
20 | }),
21 | ],
22 | transformers: [transformerDirective()],
23 | }),
24 | react(),
25 | ],
26 | resolve: {
27 | alias: [
28 | {
29 | find: '@',
30 | replacement: path.resolve(__dirname, 'src'),
31 | },
32 | ],
33 | },
34 | build: {
35 | outDir: './output',
36 | reportCompressedSize: false,
37 | },
38 | })
39 |
--------------------------------------------------------------------------------
/packages/event/src/index.ts:
--------------------------------------------------------------------------------
1 | import mincuCore from 'mincu-core'
2 | import { ShareConfig } from 'mincu-core'
3 |
4 | export class EventModule {
5 | static Instance() {
6 | return new EventModule()
7 | }
8 |
9 | /**
10 | * 通过系统默认浏览器打开 Web 页面
11 | *
12 | * 主要适配一些端内转端外场景和 deeplink
13 | *
14 | * @param url - 要跳转的链接
15 | */
16 | openUrl(url: string) {
17 | mincuCore.call('Linking', 'openURL', [url], () => {
18 | console.log(`${url} 已打开`)
19 | })
20 | }
21 |
22 | setShareConfig(config: ShareConfig) {
23 | mincuCore.call('Share', 'setShareConfig', [config], () => {
24 | console.log('配置分享设置')
25 | })
26 | }
27 |
28 | showShare() {
29 | mincuCore.call('Share', 'openShareMenu', null, () => {
30 | console.log('打开分享弹框')
31 | })
32 | }
33 |
34 | login(username: string, password: string) {
35 | mincuCore.call('Auth', 'login', [{ username, password }], () => {
36 | console.log('登录')
37 | })
38 | }
39 | }
40 |
41 | export default EventModule.Instance()
42 |
--------------------------------------------------------------------------------
/packages/debug/src/mincud/commands/vscode.ts:
--------------------------------------------------------------------------------
1 | import execa from 'execa'
2 |
3 | const isRunningOutput = (output: string) => {
4 | return (
5 | output.includes('Version:') &&
6 | output.includes('Code') &&
7 | output.includes('OS Version:') &&
8 | output.includes('electron_node')
9 | )
10 | }
11 |
12 | /**
13 | * Check if VSCode is running, through the `code -s` command.
14 | * @returns Promise
15 | */
16 | export const isVsCodeRunning = () => {
17 | return new Promise((_resolve) => {
18 | const {
19 | stdout,
20 | catch: catching,
21 | kill,
22 | } = execa('code', ['-s', '--disable-extensions', '--disable-gpu'])
23 | const resolve = (out: any) => {
24 | kill()
25 | _resolve(out)
26 | }
27 | catching(() => resolve(false))
28 | if (stdout) {
29 | stdout.on('data', (data) => {
30 | if (isRunningOutput(data.toString())) {
31 | resolve(true)
32 | } else {
33 | resolve(false)
34 | }
35 | })
36 | } else {
37 | resolve(false)
38 | }
39 | })
40 | }
41 |
--------------------------------------------------------------------------------
/packages/lib/src/debug.ts:
--------------------------------------------------------------------------------
1 | import { _window } from './utils'
2 |
3 | export const REGEXP_NETWORK_HOST =
4 | /(http:\/\/([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+):([0-9]+))/g
5 | export const REGEXP_LOCAL_HOST = /(http:\/\/localhost:([0-9]+))/g
6 |
7 | export const CMD_RELOAD = 'CMD_RELOAD'
8 | export const CMD_DEV_TOOL = 'CMD_DEV_TOOL'
9 |
10 | export const enum CHII_EVENT {
11 | CONNECTED,
12 | TARGET_CHANGED,
13 | }
14 |
15 | export const DEBUG_CHII_PORT = 2334
16 | export const DEBUG_PORT = 2333
17 | export const DEBUG_HOST = _window.location?.hostname || 'localhost'
18 | export const LOG_LEVELS: LogLevel[] = [
19 | 'trace',
20 | 'info',
21 | 'warn',
22 | 'error',
23 | 'log',
24 | 'group',
25 | 'groupCollapsed',
26 | 'groupEnd',
27 | 'debug',
28 | ]
29 |
30 | export type LogLevel =
31 | | 'trace'
32 | | 'info'
33 | | 'warn'
34 | | 'error'
35 | | 'log'
36 | | 'group'
37 | | 'groupCollapsed'
38 | | 'groupEnd'
39 | | 'debug'
40 |
41 | export type RecvType = 'log' | 'command'
42 |
43 | export interface Received {
44 | type: RecvType
45 | level?: LogLevel
46 | data: string[]
47 | }
48 |
--------------------------------------------------------------------------------
/packages/ui/src/back-press.ts:
--------------------------------------------------------------------------------
1 | import mincuCore from 'mincu-core'
2 |
3 | export const backPress = {
4 | /**
5 | * 绑定原生返回事件
6 | * 目前的限制:只有当 App 的 Header 已显示时才能绑定原生返回事件,才会触发返回回调,防止用户无法退出 WebView 页面
7 | * const cb = () => {}
8 | * const unbind = uiModule.backPress.bind(cb)
9 | * // 取消绑定
10 | * unbind()
11 | * // 或者
12 | * uiModule.backPress.unbind(cb)
13 | * @param cb 触发返回事件时的回调
14 | * @param onResulst 绑定结果,成功或失败
15 | */
16 | bind: (cb: () => void, onResulst?: (success: boolean) => void) => {
17 | mincuCore.call(
18 | 'Webview',
19 | 'bindBackPress',
20 | [true],
21 | () => {
22 | onResulst?.(true)
23 | mincuCore.listener('back-press', cb)
24 | },
25 | () => {
26 | console.error('绑定原生返回事件失败, 请先显示 header')
27 | onResulst?.(false)
28 | }
29 | )
30 | return () => {
31 | backPress.unbind(cb)
32 | }
33 | },
34 | /**
35 | * 取消绑定原生返回事件
36 | */
37 | unbind: (cb: () => void) => {
38 | mincuCore.call('Webview', 'bindBackPress', [false], () => {
39 | mincuCore.remove('back-press', cb)
40 | })
41 | },
42 | }
43 |
--------------------------------------------------------------------------------
/packages/ui/src/index.ts:
--------------------------------------------------------------------------------
1 | import mincuCore from 'mincu-core'
2 | import { NavConfig, StatusBarStyle } from 'mincu-core'
3 | import { backPress } from './back-press'
4 | import { toast } from './toast'
5 | import { orientation } from './orientation'
6 |
7 | export class UIModule {
8 | static Instance() {
9 | return new UIModule()
10 | }
11 |
12 | toast = toast
13 |
14 | backPress = backPress
15 |
16 | /**
17 | * @since iNCU 5.9.7+
18 | */
19 | orientation = orientation
20 |
21 | setBarStyle(style: StatusBarStyle) {
22 | mincuCore.call('StatusBar', 'setBarStyle', [style])
23 | }
24 |
25 | handleShowHeader(value: boolean): Promise {
26 | return new Promise((resolve) => {
27 | mincuCore.call('Webview', 'handleShowHeader', [value], (res) => {
28 | resolve(res.data)
29 | })
30 | })
31 | }
32 |
33 | toScreen(config: NavConfig) {
34 | mincuCore.call('Webview', 'toScreen', [config])
35 | }
36 |
37 | exit() {
38 | mincuCore.call('Webview', 'exitWebView', null, () => {
39 | console.log('退出微应用')
40 | })
41 | }
42 | }
43 |
44 | export default UIModule.Instance()
45 |
--------------------------------------------------------------------------------
/example/react-vite/deploy-vercel.js:
--------------------------------------------------------------------------------
1 | // mincu-react-vite
2 | const { execSync } = require('child_process');
3 | const cloneDeep = require('lodash/cloneDeep')
4 |
5 | const fs = require('fs');
6 | const path = require('path');
7 |
8 | const rewrite = (pkgPath) => {
9 | const pkgContent = fs.readFileSync(pkgPath, 'utf8')
10 | const pkgJson = JSON.parse(pkgContent)
11 | const clonedJson = cloneDeep(pkgJson)
12 | const { dependencies, devDependencies } = clonedJson
13 |
14 | for (const [key, value] of Object.entries(dependencies)) {
15 | dependencies[key] = value.replace('workspace:', '')
16 | }
17 |
18 | for (const [key, value] of Object.entries(devDependencies)) {
19 | devDependencies[key] = value.replace('workspace:', '')
20 | }
21 |
22 | fs.writeFileSync(pkgPath, JSON.stringify(clonedJson, null, 2))
23 |
24 | return () => {
25 | fs.writeFileSync(pkgPath, pkgContent)
26 | }
27 | }
28 |
29 | const pwdPkgPath = path.join(__dirname, './package.json')
30 | const recoverPwdPkg = rewrite(pwdPkgPath)
31 |
32 | try {
33 | execSync('vercel --prod', {
34 | stdio: 'inherit'
35 | })
36 | } catch (error) {
37 | throw error
38 | } finally {
39 | recoverPwdPkg()
40 | }
41 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | import { useSearchParam } from 'react-use'
2 | import { DEBUG_CHII_PORT } from 'mincu-lib/debug'
3 |
4 | export const DEFAULT_HINT =
5 | '请打开 「南大家园」 - 「生活板块」 - 右上角「扫一扫」,扫描以上二维码,开始调试'
6 |
7 | export const API_HOST = import.meta.env.DEV
8 | ? `http://localhost:23333/api`
9 | : '/api'
10 |
11 | export const useDecodeUrl = () => {
12 | const urlParam = useSearchParam('url') || ''
13 | return urlParam ? decodeURIComponent(urlParam) : ''
14 | }
15 |
16 | export const previewUrl = async (url: string) => {
17 | const res = await fetch(
18 | `${API_HOST}/preview?target=${encodeURIComponent(url)}`
19 | )
20 | return res.json()
21 | }
22 |
23 | export const setThemeClass = (isDark: boolean) => {
24 | if (isDark) {
25 | document.documentElement.classList.remove('light')
26 | document.documentElement.classList.add('dark')
27 | } else {
28 | document.documentElement.classList.remove('dark')
29 | document.documentElement.classList.add('light')
30 | }
31 | }
32 |
33 | export const CHII_URL = `http://localhost:${DEBUG_CHII_PORT}`
34 |
35 | export const chiiFrontUrl = (clientId: string, targetId: string) =>
36 | `${CHII_URL}/front_end/chii_app.html?ws=localhost:${DEBUG_CHII_PORT}/client/${clientId}?target=${targetId}`
37 |
--------------------------------------------------------------------------------
/packages/data/src/index.ts:
--------------------------------------------------------------------------------
1 | import mincuCore from 'mincu-core'
2 | import { AppData, EdgeInsets } from 'mincu-core'
3 | import { defaultUserData } from 'mincu-lib'
4 | import { MincuStorage } from './storage'
5 |
6 | export class DataModule {
7 | static Instance() {
8 | return new DataModule()
9 | }
10 |
11 | storage = new MincuStorage()
12 |
13 | get isDark() {
14 | return this.colorScheme === 'dark'
15 | }
16 |
17 | get appData() {
18 | if (!mincuCore.appData) {
19 | return {
20 | user: defaultUserData,
21 | } as AppData
22 | }
23 | return mincuCore.appData
24 | }
25 |
26 | get isApp() {
27 | return mincuCore.isApp
28 | }
29 |
30 | get userInfo(): AppData['user'] {
31 | return this.appData.user
32 | }
33 |
34 | get colors() {
35 | return this.appData.user.colors
36 | }
37 |
38 | get colorScheme() {
39 | return this.appData.user.colorScheme
40 | }
41 |
42 | get inset(): EdgeInsets {
43 | return this.appData.user.inset
44 | }
45 |
46 | async getVersion(): Promise {
47 | return new Promise((resolve) => {
48 | mincuCore.call('DeviceInfo', 'getVersion', null, (res) => {
49 | resolve(res.data)
50 | })
51 | })
52 | }
53 | }
54 |
55 | export default DataModule.Instance()
56 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/components/Debuggable.tsx:
--------------------------------------------------------------------------------
1 | import { FC, useEffect, useState } from 'react'
2 | import { previewUrl } from '../utils'
3 | import type { SitePreview, DebugTarget } from '../shim'
4 | import clsx from 'clsx'
5 |
6 | const Debuggable: FC<{
7 | data: DebugTarget
8 | onClick: () => void
9 | active?: boolean
10 | }> = ({ data, onClick, active }) => {
11 | const { url } = data
12 | const [preview, setPreview] = useState()
13 | const finalTitle = preview?.title || ''
14 |
15 | useEffect(() => {
16 | checkUsable()
17 | }, [data])
18 |
19 | const checkUsable = async () => {
20 | if (!url) return
21 | const res = await previewUrl(url)
22 | setPreview(res)
23 | }
24 |
25 | return (
26 |
40 | )
41 | }
42 |
43 | export default Debuggable
44 |
--------------------------------------------------------------------------------
/packages/debug/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mincu-debug",
3 | "version": "2.13.2",
4 | "homepage": "https://github.com/ncuhome",
5 | "repository": {
6 | "type": "git",
7 | "url": "git@github.com:ncuhome/mincu.git"
8 | },
9 | "license": "MIT",
10 | "main": "dist/mincu-debug.cjs.js",
11 | "module": "dist/mincu-debug.esm.js",
12 | "bin": {
13 | "mincud": "./bin.js",
14 | "mincu-debug": "./bin.js"
15 | },
16 | "files": [
17 | "dist",
18 | "mincud"
19 | ],
20 | "dependencies": {
21 | "chalk": "^4.1.2",
22 | "console-feed-node-transform": "^3.3.0",
23 | "cross-spawn": "^7.0.3",
24 | "execa": "^5.1.1",
25 | "internal-ip": "^6.2.0",
26 | "isomorphic-ws": "^4.0.1",
27 | "lodash.debounce": "^4.0.8",
28 | "meow": "9.0.0",
29 | "mincu-chii": "^1.1.0",
30 | "mincu-debug-tools": "workspace:2.13.2",
31 | "mincu-lib": "workspace:2.13.2",
32 | "open": "^8.4.0",
33 | "strip-ansi": "6.0.0",
34 | "terminate": "^2.5.0",
35 | "v8-compile-cache": "^2.3.0",
36 | "ws": "^8.6.0"
37 | },
38 | "devDependencies": {
39 | "@types/lodash.debounce": "^4.0.7",
40 | "@types/node": "^17.0.35",
41 | "@types/ws": "^8.5.3"
42 | },
43 | "preconstruct": {
44 | "entrypoints": [
45 | "index.ts",
46 | "mincud/cli.ts"
47 | ]
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/components/SiteInfo.tsx:
--------------------------------------------------------------------------------
1 | import clsx from 'clsx'
2 | import { FC } from 'react'
3 | import type { SitePreview } from '../shim'
4 | import Space from './Space'
5 |
6 | const SiteInfo: FC<{
7 | preview?: SitePreview
8 | }> = ({ preview }) => {
9 | if (!preview) return oops
10 | return (
11 |
18 |
19 |
20 |

24 |
25 |
26 | {preview.title}
27 | {preview.siteName ? ` | ${preview.siteName}` : ''}
28 |
29 |
30 | {preview.mediaType},{preview.contentType}
31 |
32 |
33 |
34 | {preview.description &&
{preview.description}
}
35 |
36 |

40 |
41 | )
42 | }
43 |
44 | export default SiteInfo
45 |
--------------------------------------------------------------------------------
/packages/lib/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [2.13.2](https://github.com/ncuhome/mincu/compare/v2.13.1...v2.13.2) (2023-04-23)
7 |
8 | **Note:** Version bump only for package mincu-lib
9 |
10 | ## [2.13.1](https://github.com/ncuhome/mincu/compare/v2.13.0...v2.13.1) (2023-04-23)
11 |
12 | **Note:** Version bump only for package mincu-lib
13 |
14 | # [2.12.0](https://github.com/ncuhome/mincu/compare/v2.11.0...v2.12.0) (2022-09-07)
15 |
16 | **Note:** Version bump only for package mincu-lib
17 |
18 | # [2.11.0](https://github.com/ncuhome/mincu/compare/v2.10.3...v2.11.0) (2022-08-25)
19 |
20 | **Note:** Version bump only for package mincu-lib
21 |
22 | ## [2.10.1](https://github.com/ncuhome/mincu/compare/v2.10.0...v2.10.1) (2022-08-19)
23 |
24 | **Note:** Version bump only for package mincu-lib
25 |
26 | ## [2.8.1](https://github.com/ncuhome/mincu/compare/v2.8.0...v2.8.1) (2022-08-11)
27 |
28 | **Note:** Version bump only for package mincu-lib
29 |
30 | # [2.8.0](https://github.com/ncuhome/mincu/compare/v2.7.0...v2.8.0) (2022-08-08)
31 |
32 | **Note:** Version bump only for package mincu-lib
33 |
34 | ## [2.7.2](https://github.com/ncuhome/mincu/compare/v2.7.1...v2.7.2) (2022-08-08)
35 |
36 | **Note:** Version bump only for package mincu-lib
37 |
--------------------------------------------------------------------------------
/packages/create/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [2.13.2](https://github.com/ncuhome/mincu/compare/v2.13.1...v2.13.2) (2023-04-23)
7 |
8 | **Note:** Version bump only for package create-mincu
9 |
10 | ## [2.13.1](https://github.com/ncuhome/mincu/compare/v2.13.0...v2.13.1) (2023-04-23)
11 |
12 | **Note:** Version bump only for package create-mincu
13 |
14 | # [2.12.0](https://github.com/ncuhome/mincu/compare/v2.11.0...v2.12.0) (2022-09-07)
15 |
16 | **Note:** Version bump only for package create-mincu
17 |
18 | # [2.11.0](https://github.com/ncuhome/mincu/compare/v2.10.3...v2.11.0) (2022-08-25)
19 |
20 | **Note:** Version bump only for package create-mincu
21 |
22 | ## [2.10.1](https://github.com/ncuhome/mincu/compare/v2.10.0...v2.10.1) (2022-08-19)
23 |
24 | **Note:** Version bump only for package create-mincu
25 |
26 | ## [2.8.1](https://github.com/ncuhome/mincu/compare/v2.8.0...v2.8.1) (2022-08-11)
27 |
28 | **Note:** Version bump only for package create-mincu
29 |
30 | # [2.8.0](https://github.com/ncuhome/mincu/compare/v2.7.0...v2.8.0) (2022-08-08)
31 |
32 | **Note:** Version bump only for package create-mincu
33 |
34 | ## [2.7.2](https://github.com/ncuhome/mincu/compare/v2.7.1...v2.7.2) (2022-08-08)
35 |
36 | **Note:** Version bump only for package create-mincu
37 |
--------------------------------------------------------------------------------
/example/vue-vite/README.md:
--------------------------------------------------------------------------------
1 | # Vue 3 + TypeScript + Vite
2 |
3 | This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/packages/react/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [2.13.2](https://github.com/ncuhome/mincu/compare/v2.13.1...v2.13.2) (2023-04-23)
7 |
8 | **Note:** Version bump only for package mincu-react
9 |
10 | ## [2.13.1](https://github.com/ncuhome/mincu/compare/v2.13.0...v2.13.1) (2023-04-23)
11 |
12 | **Note:** Version bump only for package mincu-react
13 |
14 | # [2.12.0](https://github.com/ncuhome/mincu/compare/v2.11.0...v2.12.0) (2022-09-07)
15 |
16 | **Note:** Version bump only for package mincu-react
17 |
18 | # [2.11.0](https://github.com/ncuhome/mincu/compare/v2.10.3...v2.11.0) (2022-08-25)
19 |
20 | **Note:** Version bump only for package mincu-react
21 |
22 | ## [2.10.3](https://github.com/ncuhome/mincu/compare/v2.10.2...v2.10.3) (2022-08-24)
23 |
24 | **Note:** Version bump only for package mincu-react
25 |
26 | ## [2.10.2](https://github.com/ncuhome/mincu/compare/v2.10.1...v2.10.2) (2022-08-23)
27 |
28 | ### Bug Fixes
29 |
30 | * workspace deps pin version ([d89ccac](https://github.com/ncuhome/mincu/commit/d89ccacb4085ac5d020219b202343da433743942))
31 |
32 | ## [2.10.1](https://github.com/ncuhome/mincu/compare/v2.10.0...v2.10.1) (2022-08-19)
33 |
34 | **Note:** Version bump only for package mincu-react
35 |
36 | # [2.9.0](https://github.com/ncuhome/mincu/compare/v2.8.3...v2.9.0) (2022-08-19)
37 |
38 | **Note:** Version bump only for package mincu-react
39 |
40 | ## [2.8.3](https://github.com/ncuhome/mincu/compare/v2.8.2...v2.8.3) (2022-08-13)
41 |
42 | **Note:** Version bump only for package mincu-react
43 |
44 | ## [2.8.2](https://github.com/ncuhome/mincu/compare/v2.8.1...v2.8.2) (2022-08-12)
45 |
46 | **Note:** Version bump only for package mincu-react
47 |
48 | ## [2.8.1](https://github.com/ncuhome/mincu/compare/v2.8.0...v2.8.1) (2022-08-11)
49 |
50 | **Note:** Version bump only for package mincu-react
51 |
52 | # [2.8.0](https://github.com/ncuhome/mincu/compare/v2.7.0...v2.8.0) (2022-08-08)
53 |
54 | **Note:** Version bump only for package mincu-react
55 |
56 | ## [2.7.2](https://github.com/ncuhome/mincu/compare/v2.7.1...v2.7.2) (2022-08-08)
57 |
58 | **Note:** Version bump only for package mincu-react
59 |
--------------------------------------------------------------------------------
/packages/ui/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [2.13.2](https://github.com/ncuhome/mincu/compare/v2.13.1...v2.13.2) (2023-04-23)
7 |
8 | **Note:** Version bump only for package mincu-ui
9 |
10 | ## [2.13.1](https://github.com/ncuhome/mincu/compare/v2.13.0...v2.13.1) (2023-04-23)
11 |
12 | **Note:** Version bump only for package mincu-ui
13 |
14 | # [2.12.0](https://github.com/ncuhome/mincu/compare/v2.11.0...v2.12.0) (2022-09-07)
15 |
16 | **Note:** Version bump only for package mincu-ui
17 |
18 | # [2.11.0](https://github.com/ncuhome/mincu/compare/v2.10.3...v2.11.0) (2022-08-25)
19 |
20 | **Note:** Version bump only for package mincu-ui
21 |
22 | ## [2.10.2](https://github.com/ncuhome/mincu/compare/v2.10.1...v2.10.2) (2022-08-23)
23 |
24 | ### Bug Fixes
25 |
26 | * workspace deps pin version ([d89ccac](https://github.com/ncuhome/mincu/commit/d89ccacb4085ac5d020219b202343da433743942))
27 |
28 | ## [2.10.1](https://github.com/ncuhome/mincu/compare/v2.10.0...v2.10.1) (2022-08-19)
29 |
30 | **Note:** Version bump only for package mincu-ui
31 |
32 | # [2.9.0](https://github.com/ncuhome/mincu/compare/v2.8.3...v2.9.0) (2022-08-19)
33 |
34 | ### Features
35 |
36 | * mincu-{core, event} -> orientation API ([5e5467a](https://github.com/ncuhome/mincu/commit/5e5467a7199276c99460f11e5e428afd49354862))
37 |
38 | ## [2.8.3](https://github.com/ncuhome/mincu/compare/v2.8.2...v2.8.3) (2022-08-13)
39 |
40 | **Note:** Version bump only for package mincu-ui
41 |
42 | ## [2.8.2](https://github.com/ncuhome/mincu/compare/v2.8.1...v2.8.2) (2022-08-12)
43 |
44 | ### Features
45 |
46 | * mincu-core fill interface ([c29a122](https://github.com/ncuhome/mincu/commit/c29a122d2980332e959b4bd9960a3bd09b56f72c))
47 |
48 | ## [2.8.1](https://github.com/ncuhome/mincu/compare/v2.8.0...v2.8.1) (2022-08-11)
49 |
50 | **Note:** Version bump only for package mincu-ui
51 |
52 | # [2.8.0](https://github.com/ncuhome/mincu/compare/v2.7.0...v2.8.0) (2022-08-08)
53 |
54 | **Note:** Version bump only for package mincu-ui
55 |
56 | ## [2.7.2](https://github.com/ncuhome/mincu/compare/v2.7.1...v2.7.2) (2022-08-08)
57 |
58 | **Note:** Version bump only for package mincu-ui
59 |
--------------------------------------------------------------------------------
/packages/network/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [2.13.2](https://github.com/ncuhome/mincu/compare/v2.13.1...v2.13.2) (2023-04-23)
7 |
8 | **Note:** Version bump only for package mincu-network
9 |
10 | ## [2.13.1](https://github.com/ncuhome/mincu/compare/v2.13.0...v2.13.1) (2023-04-23)
11 |
12 | **Note:** Version bump only for package mincu-network
13 |
14 | # [2.12.0](https://github.com/ncuhome/mincu/compare/v2.11.0...v2.12.0) (2022-09-07)
15 |
16 | **Note:** Version bump only for package mincu-network
17 |
18 | # [2.11.0](https://github.com/ncuhome/mincu/compare/v2.10.3...v2.11.0) (2022-08-25)
19 |
20 | **Note:** Version bump only for package mincu-network
21 |
22 | ## [2.10.3](https://github.com/ncuhome/mincu/compare/v2.10.2...v2.10.3) (2022-08-24)
23 |
24 | ### Bug Fixes
25 |
26 | * mincu-network -> handleTokenExpired expired check ([8375038](https://github.com/ncuhome/mincu/commit/8375038797ef4515e3d7fd8b7f2431bb05703da7))
27 |
28 | ## [2.10.2](https://github.com/ncuhome/mincu/compare/v2.10.1...v2.10.2) (2022-08-23)
29 |
30 | ### Bug Fixes
31 |
32 | * workspace deps pin version ([d89ccac](https://github.com/ncuhome/mincu/commit/d89ccacb4085ac5d020219b202343da433743942))
33 |
34 | ## [2.10.1](https://github.com/ncuhome/mincu/compare/v2.10.0...v2.10.1) (2022-08-19)
35 |
36 | **Note:** Version bump only for package mincu-network
37 |
38 | # [2.9.0](https://github.com/ncuhome/mincu/compare/v2.8.3...v2.9.0) (2022-08-19)
39 |
40 | **Note:** Version bump only for package mincu-network
41 |
42 | ## [2.8.3](https://github.com/ncuhome/mincu/compare/v2.8.2...v2.8.3) (2022-08-13)
43 |
44 | **Note:** Version bump only for package mincu-network
45 |
46 | ## [2.8.2](https://github.com/ncuhome/mincu/compare/v2.8.1...v2.8.2) (2022-08-12)
47 |
48 | **Note:** Version bump only for package mincu-network
49 |
50 | ## [2.8.1](https://github.com/ncuhome/mincu/compare/v2.8.0...v2.8.1) (2022-08-11)
51 |
52 | **Note:** Version bump only for package mincu-network
53 |
54 | # [2.8.0](https://github.com/ncuhome/mincu/compare/v2.7.0...v2.8.0) (2022-08-08)
55 |
56 | **Note:** Version bump only for package mincu-network
57 |
58 | ## [2.7.2](https://github.com/ncuhome/mincu/compare/v2.7.1...v2.7.2) (2022-08-08)
59 |
60 | **Note:** Version bump only for package mincu-network
61 |
--------------------------------------------------------------------------------
/packages/debug/src/mincud/logToConsole.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Facebook, Inc. and its affiliates.
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | *
7 | * @see https://github.com/facebook/metro/blob/master/packages/metro/src/lib/logToConsole.js
8 | */
9 | import chalk from 'chalk'
10 | import util from 'util'
11 | import { LogLevel } from 'mincu-lib/debug'
12 |
13 | const groupStack = []
14 | let collapsedGuardTimer
15 |
16 | export const logToConsole = (level: LogLevel, data: any[]) => {
17 | const logFunction = console[level] && level !== 'trace' ? level : 'log'
18 | const color =
19 | level === 'error'
20 | ? chalk.inverse.red
21 | : level === 'warn'
22 | ? chalk.inverse.yellow
23 | : level === 'info'
24 | ? chalk.inverse.blue
25 | : chalk.inverse.white
26 |
27 | if (level === 'group') {
28 | groupStack.push(level)
29 | } else if (level === 'groupCollapsed') {
30 | groupStack.push(level)
31 | clearTimeout(collapsedGuardTimer)
32 | // Inform users that logs get swallowed if they forget to call `groupEnd`.
33 | collapsedGuardTimer = setTimeout(() => {
34 | if (groupStack.includes('groupCollapsed')) {
35 | console.log(
36 | chalk.inverse.yellow.bold(' WARN '),
37 | 'Expected `console.groupEnd` to be called after `console.groupCollapsed`.'
38 | )
39 | groupStack.length = 0
40 | }
41 | }, 3000)
42 | return
43 | } else if (level === 'groupEnd') {
44 | groupStack.pop()
45 | if (!groupStack.length) {
46 | clearTimeout(collapsedGuardTimer)
47 | }
48 | return
49 | }
50 |
51 | if (!groupStack.includes('groupCollapsed')) {
52 | // Remove excess whitespace at the end of a log message, if possible.
53 | const lastItem = data[data.length - 1]
54 | if (typeof lastItem === 'string') {
55 | data[data.length - 1] = lastItem.trimEnd()
56 | }
57 |
58 | console.log(
59 | color.bold(` ${logFunction.toUpperCase()} `) +
60 | ''.padEnd(groupStack.length * 2, ' '),
61 | // `util.format` actually accepts any arguments.
62 | // If the first argument is a string, it tries to format it.
63 | // Otherwise, it just concatenates all arguments.
64 | // $FlowIssue[incompatible-call] util.format expected the first argument to be a string
65 | util.format(...data)
66 | )
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/packages/demos/react-demo-shared/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [2.13.2](https://github.com/ncuhome/mincu/compare/v2.13.1...v2.13.2) (2023-04-23)
7 |
8 | **Note:** Version bump only for package mincu-react-demo-shared
9 |
10 | ## [2.13.1](https://github.com/ncuhome/mincu/compare/v2.13.0...v2.13.1) (2023-04-23)
11 |
12 | **Note:** Version bump only for package mincu-react-demo-shared
13 |
14 | # [2.13.0](https://github.com/ncuhome/mincu/compare/v2.12.0...v2.13.0) (2023-04-22)
15 |
16 | ### Features
17 |
18 | * react-demo-shared copyToken ([e288e3e](https://github.com/ncuhome/mincu/commit/e288e3e0c81c98db5f35d3c04bfa0d9f22ba340d))
19 |
20 | # [2.12.0](https://github.com/ncuhome/mincu/compare/v2.11.0...v2.12.0) (2022-09-07)
21 |
22 | ### Features
23 |
24 | * demo benchmark modal ([27b34b6](https://github.com/ncuhome/mincu/commit/27b34b6905429c79c4931c6317bc7cf81ac4c843))
25 |
26 | # [2.11.0](https://github.com/ncuhome/mincu/compare/v2.10.3...v2.11.0) (2022-08-25)
27 |
28 | ### Bug Fixes
29 |
30 | * react-demo-shared button broken class ([9f355ee](https://github.com/ncuhome/mincu/commit/9f355eedbdd0371fdc62e66b81d1e98976869e87))
31 |
32 | ### Features
33 |
34 | * react-demo-shared bench case ([185a43a](https://github.com/ncuhome/mincu/commit/185a43a2f85bbb03b3d66811456534a741504213))
35 | * react-demo-shared bench iterations ([141b2e4](https://github.com/ncuhome/mincu/commit/141b2e47142f8161ed0280bd771927517c6542d8))
36 |
37 | ## [2.10.3](https://github.com/ncuhome/mincu/compare/v2.10.2...v2.10.3) (2022-08-24)
38 |
39 | **Note:** Version bump only for package mincu-react-demo-shared
40 |
41 | ## [2.10.2](https://github.com/ncuhome/mincu/compare/v2.10.1...v2.10.2) (2022-08-23)
42 |
43 | **Note:** Version bump only for package mincu-react-demo-shared
44 |
45 | ## [2.10.1](https://github.com/ncuhome/mincu/compare/v2.10.0...v2.10.1) (2022-08-19)
46 |
47 | **Note:** Version bump only for package mincu-react-demo-shared
48 |
49 | # [2.10.0](https://github.com/ncuhome/mincu/compare/v2.9.1...v2.10.0) (2022-08-19)
50 |
51 | ### Features
52 |
53 | * demos/react-demo-shared use twind ([01d67d3](https://github.com/ncuhome/mincu/commit/01d67d379f29584bf7e8ff6813dfb1bc3289d499))
54 |
55 | ## [2.9.1](https://github.com/ncuhome/mincu/compare/v2.9.0...v2.9.1) (2022-08-19)
56 |
57 | **Note:** Version bump only for package mincu-react-demo-shared
58 |
--------------------------------------------------------------------------------
/packages/vanilla/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [2.13.2](https://github.com/ncuhome/mincu/compare/v2.13.1...v2.13.2) (2023-04-23)
7 |
8 | **Note:** Version bump only for package mincu-vanilla
9 |
10 | ## [2.13.1](https://github.com/ncuhome/mincu/compare/v2.13.0...v2.13.1) (2023-04-23)
11 |
12 | **Note:** Version bump only for package mincu-vanilla
13 |
14 | # [2.12.0](https://github.com/ncuhome/mincu/compare/v2.11.0...v2.12.0) (2022-09-07)
15 |
16 | **Note:** Version bump only for package mincu-vanilla
17 |
18 | # [2.11.0](https://github.com/ncuhome/mincu/compare/v2.10.3...v2.11.0) (2022-08-25)
19 |
20 | **Note:** Version bump only for package mincu-vanilla
21 |
22 | ## [2.10.3](https://github.com/ncuhome/mincu/compare/v2.10.2...v2.10.3) (2022-08-24)
23 |
24 | **Note:** Version bump only for package mincu-vanilla
25 |
26 | ## [2.10.2](https://github.com/ncuhome/mincu/compare/v2.10.1...v2.10.2) (2022-08-23)
27 |
28 | ### Bug Fixes
29 |
30 | * workspace deps pin version ([d89ccac](https://github.com/ncuhome/mincu/commit/d89ccacb4085ac5d020219b202343da433743942))
31 |
32 | ## [2.10.1](https://github.com/ncuhome/mincu/compare/v2.10.0...v2.10.1) (2022-08-19)
33 |
34 | **Note:** Version bump only for package mincu-vanilla
35 |
36 | # [2.9.0](https://github.com/ncuhome/mincu/compare/v2.8.3...v2.9.0) (2022-08-19)
37 |
38 | **Note:** Version bump only for package mincu-vanilla
39 |
40 | ## [2.8.3](https://github.com/ncuhome/mincu/compare/v2.8.2...v2.8.3) (2022-08-13)
41 |
42 | **Note:** Version bump only for package mincu-vanilla
43 |
44 | ## [2.8.2](https://github.com/ncuhome/mincu/compare/v2.8.1...v2.8.2) (2022-08-12)
45 |
46 | **Note:** Version bump only for package mincu-vanilla
47 |
48 | ## [2.8.1](https://github.com/ncuhome/mincu/compare/v2.8.0...v2.8.1) (2022-08-11)
49 |
50 | ### Features
51 |
52 | * mincu-vanilla export Mincu interface ([5b4d4df](https://github.com/ncuhome/mincu/commit/5b4d4dfb4a3c1ba3b08290b465b05cb742fd0b1e))
53 |
54 | # [2.8.0](https://github.com/ncuhome/mincu/compare/v2.7.0...v2.8.0) (2022-08-08)
55 |
56 | ### Bug Fixes
57 |
58 | * **mincu-vanilla:** mincu variables ([736f454](https://github.com/ncuhome/mincu/commit/736f454ba717a5b6d831b18f637dbd02bcdce60d))
59 |
60 | ## [2.7.2](https://github.com/ncuhome/mincu/compare/v2.7.1...v2.7.2) (2022-08-08)
61 |
62 | **Note:** Version bump only for package mincu-vanilla
63 |
--------------------------------------------------------------------------------
/packages/core/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [2.13.2](https://github.com/ncuhome/mincu/compare/v2.13.1...v2.13.2) (2023-04-23)
7 |
8 | **Note:** Version bump only for package mincu-core
9 |
10 | ## [2.13.1](https://github.com/ncuhome/mincu/compare/v2.13.0...v2.13.1) (2023-04-23)
11 |
12 | **Note:** Version bump only for package mincu-core
13 |
14 | # [2.12.0](https://github.com/ncuhome/mincu/compare/v2.11.0...v2.12.0) (2022-09-07)
15 |
16 | **Note:** Version bump only for package mincu-core
17 |
18 | # [2.11.0](https://github.com/ncuhome/mincu/compare/v2.10.3...v2.11.0) (2022-08-25)
19 |
20 | **Note:** Version bump only for package mincu-core
21 |
22 | ## [2.10.2](https://github.com/ncuhome/mincu/compare/v2.10.1...v2.10.2) (2022-08-23)
23 |
24 | ### Bug Fixes
25 |
26 | * workspace deps pin version ([d89ccac](https://github.com/ncuhome/mincu/commit/d89ccacb4085ac5d020219b202343da433743942))
27 |
28 | ## [2.10.1](https://github.com/ncuhome/mincu/compare/v2.10.0...v2.10.1) (2022-08-19)
29 |
30 | **Note:** Version bump only for package mincu-core
31 |
32 | # [2.9.0](https://github.com/ncuhome/mincu/compare/v2.8.3...v2.9.0) (2022-08-19)
33 |
34 | ### Features
35 |
36 | * mincu-{core, event} -> orientation API ([5e5467a](https://github.com/ncuhome/mincu/commit/5e5467a7199276c99460f11e5e428afd49354862))
37 | * mincu-core -> makeProxyFromNativeFunc ([78eacfc](https://github.com/ncuhome/mincu/commit/78eacfc6998fb2dda213531e1b8daea9b836f2ec))
38 |
39 | ## [2.8.3](https://github.com/ncuhome/mincu/compare/v2.8.2...v2.8.3) (2022-08-13)
40 |
41 | ### Bug Fixes
42 |
43 | * mincu-core call failed signature ([9f9463b](https://github.com/ncuhome/mincu/commit/9f9463be83f615e37f20f52652cdad953e14dcf0))
44 |
45 | ## [2.8.2](https://github.com/ncuhome/mincu/compare/v2.8.1...v2.8.2) (2022-08-12)
46 |
47 | ### Features
48 |
49 | * mincu-core fill interface ([c29a122](https://github.com/ncuhome/mincu/commit/c29a122d2980332e959b4bd9960a3bd09b56f72c))
50 |
51 | ## [2.8.1](https://github.com/ncuhome/mincu/compare/v2.8.0...v2.8.1) (2022-08-11)
52 |
53 | **Note:** Version bump only for package mincu-core
54 |
55 | # [2.8.0](https://github.com/ncuhome/mincu/compare/v2.7.0...v2.8.0) (2022-08-08)
56 |
57 | ### Bug Fixes
58 |
59 | * **core:** typings ([f807452](https://github.com/ncuhome/mincu/commit/f807452e9aa62dd785a82d6275e7afe510b998b6))
60 |
61 | ## [2.7.2](https://github.com/ncuhome/mincu/compare/v2.7.1...v2.7.2) (2022-08-08)
62 |
63 | **Note:** Version bump only for package mincu-core
64 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/components/Modal.tsx:
--------------------------------------------------------------------------------
1 | import React, { cloneElement, useState, useCallback } from 'react'
2 | import {
3 | useFloating,
4 | useInteractions,
5 | useClick,
6 | useRole,
7 | useDismiss,
8 | useId,
9 | FloatingPortal,
10 | FloatingOverlay,
11 | FloatingFocusManager,
12 | } from '@floating-ui/react-dom-interactions'
13 | import { useThemeDark } from '../hooks/index'
14 |
15 | export interface Props {
16 | open?: boolean
17 | render: (props: {
18 | close: () => void
19 | labelId: string
20 | descriptionId: string
21 | }) => React.ReactNode
22 | children?: JSX.Element
23 | keepAlive?: boolean
24 | }
25 |
26 | const Modal = ({
27 | render,
28 | open: passedOpen = false,
29 | children,
30 | keepAlive = false,
31 | }: Props) => {
32 | const [open, setOpen] = useState(passedOpen)
33 |
34 | const { reference, floating, context } = useFloating({
35 | open,
36 | onOpenChange: setOpen,
37 | })
38 |
39 | const isDark = useThemeDark()
40 |
41 | const id = useId()
42 | const labelId = `${id}-label`
43 | const descriptionId = `${id}-description`
44 |
45 | const { getReferenceProps, getFloatingProps } = useInteractions([
46 | useClick(context),
47 | useRole(context),
48 | useDismiss(context),
49 | ])
50 |
51 | const Content = useCallback(
52 | () => (
53 |
60 |
61 |
68 | {render({
69 | close: () => setOpen(false),
70 | labelId,
71 | descriptionId,
72 | })}
73 |
74 |
75 |
76 | ),
77 | [isDark]
78 | )
79 |
80 | return (
81 | <>
82 | {children &&
83 | cloneElement(
84 | children,
85 | getReferenceProps({ ref: reference, ...children.props })
86 | )}
87 |
88 | {keepAlive ? (
89 |
94 |
95 |
96 | ) : (
97 | open &&
98 | )}
99 |
100 | >
101 | )
102 | }
103 |
104 | export default Modal
105 |
--------------------------------------------------------------------------------
/packages/create/src/utils.ts:
--------------------------------------------------------------------------------
1 | import fse from 'fs-extra'
2 |
3 | export function isEmpty(path: string) {
4 | return fse.readdirSync(path).length === 0
5 | }
6 |
7 | export function isValidPackageName(projectName: string) {
8 | return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(
9 | projectName
10 | )
11 | }
12 |
13 | export function toValidPackageName(projectName: string) {
14 | return projectName
15 | .trim()
16 | .toLowerCase()
17 | .replace(/\s+/g, '-')
18 | .replace(/^[._]/, '')
19 | .replace(/[^a-z0-9-~]+/g, '-')
20 | }
21 |
22 | /**
23 | * @param {string | undefined} userAgent process.env.npm_config_user_agent
24 | * @returns object | undefined
25 | */
26 | export function pkgFromUserAgent(userAgent: string) {
27 | if (!userAgent) return undefined
28 | const pkgSpec = userAgent.split(' ')[0]
29 | const pkgSpecArr = pkgSpec.split('/')
30 | return {
31 | name: pkgSpecArr[0],
32 | version: pkgSpecArr[1],
33 | }
34 | }
35 |
36 | export function logSuccessTips(name: string, pkg: Record) {
37 | const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent)
38 | const pkgManager = pkgInfo ? pkgInfo.name : 'npm'
39 |
40 | const { scripts } = pkg
41 |
42 | let startCmd
43 |
44 | if (scripts?.start) {
45 | startCmd = 'start'
46 | } else if (scripts?.dev) {
47 | startCmd = 'dev'
48 | }
49 |
50 | console.log(`
51 | 创建完毕,接下来可以:
52 |
53 | cd ${name}`)
54 |
55 | switch (pkgManager) {
56 | case 'yarn':
57 | console.log(' yarn')
58 | if (startCmd) {
59 | console.log(` yarn ${startCmd}`)
60 | }
61 | break
62 | default:
63 | console.log(` ${pkgManager} install`)
64 | if (startCmd) {
65 | console.log(` ${pkgManager} run ${startCmd}`)
66 | }
67 | break
68 | }
69 | console.log()
70 | }
71 |
72 | /**
73 | * transform package.json dependencies and devDependencies
74 | * with pnpm `workspace:` prefix back to normal npm format
75 | *
76 | * @param {Record} pkg package.json
77 | */
78 | export function transformDeps(pkg: Record) {
79 | const { dependencies, devDependencies } = pkg
80 |
81 | const replacePrefix = (dep) => {
82 | return dep.replace('workspace:', '')
83 | }
84 |
85 | if (dependencies) {
86 | Object.keys(dependencies).forEach((key) => {
87 | dependencies[key] = replacePrefix(dependencies[key])
88 | })
89 | }
90 |
91 | if (devDependencies) {
92 | Object.keys(devDependencies).forEach((key) => {
93 | devDependencies[key] = replacePrefix(devDependencies[key])
94 | })
95 | }
96 | }
97 |
98 | export const renameFiles = {
99 | _gitignore: '.gitignore',
100 | }
101 |
--------------------------------------------------------------------------------
/packages/core/src/interface.ts:
--------------------------------------------------------------------------------
1 | export * from './types/ncuos'
2 | export * from './types/rn'
3 |
4 | import { Base_info } from './types/ncuos'
5 | import {
6 | RNLinking,
7 | ToastAndroidStatic,
8 | StatusBarStyle,
9 | NetInfo,
10 | DeviceInfo,
11 | Clipboard,
12 | VibrationStatic,
13 | Orientation,
14 | } from './types/rn'
15 |
16 | export type FuncNames = keyof INativeFuncs
17 |
18 | export type States = {
19 | colors: any
20 | colorScheme: ColorSchemeName
21 | }
22 |
23 | export interface INativeFuncs {
24 | Linking: RNLinking
25 | NetInfo: NetInfo
26 | Auth: {
27 | refreshToken: () => { token: string }
28 | login: (data: { username: string; password: string }) => number
29 | }
30 | DeviceInfo: DeviceInfo
31 | Clipboard: Clipboard
32 | Vibration: VibrationStatic
33 | ToastAndroid: ToastAndroidStatic
34 | Toast: {
35 | [key: string]: (title: string, during: number) => number
36 | }
37 | StatusBar: {
38 | setBarStyle: (style: StatusBarStyle, animated?: boolean) => void
39 | }
40 | Portal: {
41 | remove: (id: number) => void
42 | }
43 | Share: {
44 | openShareMenu: () => void
45 | setShareConfig: (config: ShareConfig) => void
46 | }
47 | Webview: {
48 | handleShowHeader: (value?: boolean) => boolean
49 | disableAutoSetTitle: () => void
50 | exitWebView: () => void
51 | toScreen: (e: NavConfig) => void
52 | bindBackPress: (value: boolean) => void
53 | }
54 | Storage: {
55 | getItem: (key: string) => any
56 | setItem: (key: string, value: any) => void
57 | remove: (key: string) => void
58 | reset: () => void
59 | }
60 | /**
61 | * @since iNCU 5.9.7+
62 | */
63 | Orientation: typeof Orientation
64 | }
65 |
66 | export interface ShareConfig {
67 | title?: string
68 | url?: string
69 | imageUrl?: string
70 | }
71 |
72 | export interface NavConfig {
73 | screen: string
74 | params?: object
75 | }
76 |
77 | export interface AppData {
78 | user: {
79 | token: string
80 | colorScheme: ColorSchemeName
81 | colors: any
82 | inset: EdgeInsets
83 | profile: {
84 | basicProfile: {
85 | app_avatar_url: string | null
86 | department: string
87 | department_id: string
88 | head_pic_url: string
89 | max_role_level: number
90 | message: string
91 | name: string
92 | status: number
93 | }
94 | entireProfile: IEntireProfileResponse
95 | }
96 | }
97 | }
98 |
99 | export interface EdgeInsets {
100 | top: number
101 | right: number
102 | bottom: number
103 | left: number
104 | }
105 |
106 | export type ColorSchemeName = 'light' | 'dark' | null | undefined
107 |
108 | export interface EdgeInsets {
109 | top: number
110 | right: number
111 | bottom: number
112 | left: number
113 | }
114 |
115 | interface IEntireProfileResponse {
116 | base_info: Base_info
117 | is_teacher: boolean
118 | message: string
119 | status: number
120 | }
121 |
--------------------------------------------------------------------------------
/example/react-next/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [2.13.2](https://github.com/ncuhome/mincu/compare/v2.13.1...v2.13.2) (2023-04-23)
7 |
8 | **Note:** Version bump only for package incu-react-next-example
9 |
10 | ## [2.13.1](https://github.com/ncuhome/mincu/compare/v2.13.0...v2.13.1) (2023-04-23)
11 |
12 | **Note:** Version bump only for package incu-react-next-example
13 |
14 | # [2.13.0](https://github.com/ncuhome/mincu/compare/v2.12.0...v2.13.0) (2023-04-22)
15 |
16 | **Note:** Version bump only for package incu-react-next-example
17 |
18 | # [2.12.0](https://github.com/ncuhome/mincu/compare/v2.11.0...v2.12.0) (2022-09-07)
19 |
20 | **Note:** Version bump only for package incu-react-next-example
21 |
22 | # [2.11.0](https://github.com/ncuhome/mincu/compare/v2.10.3...v2.11.0) (2022-08-25)
23 |
24 | **Note:** Version bump only for package incu-react-next-example
25 |
26 | ## [2.10.3](https://github.com/ncuhome/mincu/compare/v2.10.2...v2.10.3) (2022-08-24)
27 |
28 | **Note:** Version bump only for package incu-react-next-example
29 |
30 | ## [2.10.2](https://github.com/ncuhome/mincu/compare/v2.10.1...v2.10.2) (2022-08-23)
31 |
32 | ### Bug Fixes
33 |
34 | * workspace deps pin version ([d89ccac](https://github.com/ncuhome/mincu/commit/d89ccacb4085ac5d020219b202343da433743942))
35 |
36 | ## [2.10.1](https://github.com/ncuhome/mincu/compare/v2.10.0...v2.10.1) (2022-08-19)
37 |
38 | **Note:** Version bump only for package incu-react-next-example
39 |
40 | # [2.10.0](https://github.com/ncuhome/mincu/compare/v2.9.1...v2.10.0) (2022-08-19)
41 |
42 | ### Features
43 |
44 | * demos/react-demo-shared use twind ([01d67d3](https://github.com/ncuhome/mincu/commit/01d67d379f29584bf7e8ff6813dfb1bc3289d499))
45 |
46 | ## [2.9.1](https://github.com/ncuhome/mincu/compare/v2.9.0...v2.9.1) (2022-08-19)
47 |
48 | **Note:** Version bump only for package incu-react-next-example
49 |
50 | # [2.9.0](https://github.com/ncuhome/mincu/compare/v2.8.3...v2.9.0) (2022-08-19)
51 |
52 | ### Features
53 |
54 | * mincu-react-demo-shared ([0093880](https://github.com/ncuhome/mincu/commit/0093880fc1fd44e141b9011784bbea3497a59365))
55 |
56 | ## [2.8.3](https://github.com/ncuhome/mincu/compare/v2.8.2...v2.8.3) (2022-08-13)
57 |
58 | **Note:** Version bump only for package incu-react-next-example
59 |
60 | ## [2.8.2](https://github.com/ncuhome/mincu/compare/v2.8.1...v2.8.2) (2022-08-12)
61 |
62 | **Note:** Version bump only for package incu-react-next-example
63 |
64 | ## [2.8.1](https://github.com/ncuhome/mincu/compare/v2.8.0...v2.8.1) (2022-08-11)
65 |
66 | **Note:** Version bump only for package incu-react-next-example
67 |
68 | # [2.8.0](https://github.com/ncuhome/mincu/compare/v2.7.0...v2.8.0) (2022-08-08)
69 |
70 | **Note:** Version bump only for package incu-react-next-example
71 |
72 | ## [2.7.2](https://github.com/ncuhome/mincu/compare/v2.7.1...v2.7.2) (2022-08-08)
73 |
74 | **Note:** Version bump only for package incu-react-next-example
75 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/app.tsx:
--------------------------------------------------------------------------------
1 | import React, { Fragment, useEffect, useState } from 'react'
2 | import Debuggable from './components/Debuggable'
3 | import { useAutoAnimate } from '@formkit/auto-animate/react'
4 | import { Allotment } from 'allotment'
5 | import SimpleBarReact from 'simplebar-react'
6 |
7 | import Space from '@/components/Space'
8 | import Inspector from '@/components/Inspector'
9 | import { useThemeWatcher, useTargets, useIp } from '@/hooks'
10 | import clsx from 'clsx'
11 | import CopyableScript from './components/CopyableScript'
12 | import { DebugTarget } from '@/shim'
13 | import { CHII_EVENT } from 'mincu-lib/debug'
14 |
15 | export const App = () => {
16 | const { targets, mutate: mutateTargets } = useTargets()
17 | const { ip } = useIp()
18 | const [parent] = useAutoAnimate()
19 | const [currentTarget, setCurrentTarget] = useState()
20 |
21 | useThemeWatcher()
22 |
23 | useEffect(() => {
24 | const ws = new WebSocket('ws://localhost:2333')
25 | ws.onmessage = async ({ data }) => {
26 | try {
27 | const { type, payload } = JSON.parse(data)
28 | console.log('TYPE', type)
29 | if (
30 | type === CHII_EVENT.TARGET_CHANGED ||
31 | type === CHII_EVENT.CONNECTED
32 | ) {
33 | mutateTargets(payload)
34 | }
35 | } catch (e) {
36 | console.error(e)
37 | }
38 | }
39 | }, [])
40 |
41 | useEffect(() => {
42 | if (currentTarget) {
43 | const valid = targets.some((it) => it.id === currentTarget.id)
44 | if (!valid) {
45 | setCurrentTarget(undefined)
46 | }
47 | }
48 | }, [targets])
49 |
50 | return (
51 |
59 | {targets.length > 0 ? (
60 | <>
61 |
62 |
63 |
67 | {targets.map((target) => (
68 |
69 | setCurrentTarget(target)}
72 | active={target.id === currentTarget?.id}
73 | />
74 |
75 |
76 | ))}
77 |
78 |
79 |
80 | {currentTarget ? (
81 |
82 | ) : (
83 |
84 | 🍺 从左侧选择要调试的应用
85 |
86 | )}
87 |
88 |
89 | >
90 | ) : (
91 |
92 |
93 |
94 | )}
95 |
96 | )
97 | }
98 |
--------------------------------------------------------------------------------
/example/react-vite/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 |
3 | All notable changes to this project will be documented in this file.
4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5 |
6 | ## [2.13.2](https://github.com/ncuhome/mincu/compare/v2.13.1...v2.13.2) (2023-04-23)
7 |
8 | **Note:** Version bump only for package vite-react-typescript-starter
9 |
10 | ## [2.13.1](https://github.com/ncuhome/mincu/compare/v2.13.0...v2.13.1) (2023-04-23)
11 |
12 | **Note:** Version bump only for package vite-react-typescript-starter
13 |
14 | # [2.13.0](https://github.com/ncuhome/mincu/compare/v2.12.0...v2.13.0) (2023-04-22)
15 |
16 | **Note:** Version bump only for package vite-react-typescript-starter
17 |
18 | # [2.12.0](https://github.com/ncuhome/mincu/compare/v2.11.0...v2.12.0) (2022-09-07)
19 |
20 | ### Bug Fixes
21 |
22 | * example/react-vite -> deploy:vercel[#2](https://github.com/ncuhome/mincu/issues/2) ([75f9f22](https://github.com/ncuhome/mincu/commit/75f9f223861c7f472d53de6046b7e2524f90242f))
23 |
24 | # [2.11.0](https://github.com/ncuhome/mincu/compare/v2.10.3...v2.11.0) (2022-08-25)
25 |
26 | ### Bug Fixes
27 |
28 | * example/react-vite -> deploy:vercel ([7cd584d](https://github.com/ncuhome/mincu/commit/7cd584d27abb40b47390a9a231c428d87e682c37))
29 |
30 | ## [2.10.3](https://github.com/ncuhome/mincu/compare/v2.10.2...v2.10.3) (2022-08-24)
31 |
32 | **Note:** Version bump only for package vite-react-typescript-starter
33 |
34 | ## [2.10.2](https://github.com/ncuhome/mincu/compare/v2.10.1...v2.10.2) (2022-08-23)
35 |
36 | ### Bug Fixes
37 |
38 | * workspace deps pin version ([d89ccac](https://github.com/ncuhome/mincu/commit/d89ccacb4085ac5d020219b202343da433743942))
39 |
40 | ## [2.10.1](https://github.com/ncuhome/mincu/compare/v2.10.0...v2.10.1) (2022-08-19)
41 |
42 | **Note:** Version bump only for package vite-react-typescript-starter
43 |
44 | # [2.10.0](https://github.com/ncuhome/mincu/compare/v2.9.1...v2.10.0) (2022-08-19)
45 |
46 | ### Features
47 |
48 | * demos/react-demo-shared use twind ([01d67d3](https://github.com/ncuhome/mincu/commit/01d67d379f29584bf7e8ff6813dfb1bc3289d499))
49 | * example/react-vite deploy-vercel ([b6b684f](https://github.com/ncuhome/mincu/commit/b6b684fae2fdfaec21be1fca0c72ebcf11117c96))
50 |
51 | ## [2.9.1](https://github.com/ncuhome/mincu/compare/v2.9.0...v2.9.1) (2022-08-19)
52 |
53 | **Note:** Version bump only for package vite-react-typescript-starter
54 |
55 | # [2.9.0](https://github.com/ncuhome/mincu/compare/v2.8.3...v2.9.0) (2022-08-19)
56 |
57 | ### Features
58 |
59 | * mincu-react-demo-shared ([0093880](https://github.com/ncuhome/mincu/commit/0093880fc1fd44e141b9011784bbea3497a59365))
60 |
61 | ## [2.8.3](https://github.com/ncuhome/mincu/compare/v2.8.2...v2.8.3) (2022-08-13)
62 |
63 | **Note:** Version bump only for package vite-react-typescript-starter
64 |
65 | ## [2.8.2](https://github.com/ncuhome/mincu/compare/v2.8.1...v2.8.2) (2022-08-12)
66 |
67 | **Note:** Version bump only for package vite-react-typescript-starter
68 |
69 | ## [2.8.1](https://github.com/ncuhome/mincu/compare/v2.8.0...v2.8.1) (2022-08-11)
70 |
71 | ### Features
72 |
73 | * upgrade deps ([015efd2](https://github.com/ncuhome/mincu/commit/015efd26a5cd4baf99d89f533c26b1df87d7b33a))
74 |
75 | # [2.8.0](https://github.com/ncuhome/mincu/compare/v2.7.0...v2.8.0) (2022-08-08)
76 |
77 | **Note:** Version bump only for package vite-react-typescript-starter
78 |
79 | ## [2.7.2](https://github.com/ncuhome/mincu/compare/v2.7.1...v2.7.2) (2022-08-08)
80 |
81 | **Note:** Version bump only for package vite-react-typescript-starter
82 |
--------------------------------------------------------------------------------
/packages/core/src/types/rn/index.ts:
--------------------------------------------------------------------------------
1 | export * from './net_info'
2 | export * from './device_info'
3 | export * from './clipboard'
4 | export * from './orientation'
5 |
6 | export interface RNLinking {
7 | /**
8 | * Try to open the given url with any of the installed apps.
9 | * You can use other URLs, like a location (e.g. "geo:37.484847,-122.148386"), a contact, or any other URL that can be opened with the installed apps.
10 | * NOTE: This method will fail if the system doesn't know how to open the specified URL. If you're passing in a non-http(s) URL, it's best to check {@code canOpenURL} first.
11 | * NOTE: For web URLs, the protocol ("http://", "https://") must be set accordingly!
12 | */
13 | openURL: (url: string) => Promise
14 |
15 | /**
16 | * Determine whether or not an installed app can handle a given URL.
17 | * NOTE: For web URLs, the protocol ("http://", "https://") must be set accordingly!
18 | * NOTE: As of iOS 9, your app needs to provide the LSApplicationQueriesSchemes key inside Info.plist.
19 | * @param URL the URL to open
20 | */
21 | canOpenURL: (url: string) => Promise
22 |
23 | /**
24 | * If the app launch was triggered by an app link with, it will give the link url, otherwise it will give null
25 | * NOTE: To support deep linking on Android, refer http://developer.android.com/training/app-indexing/deep-linking.html#handling-intents
26 | */
27 | getInitialURL: () => Promise
28 |
29 | /**
30 | * Open the Settings app and displays the app’s custom settings, if it has any.
31 | */
32 | openSettings: () => Promise
33 |
34 | /**
35 | * Sends an Android Intent - a broad surface to express Android functions. Useful for deep-linking to settings pages,
36 | * opening an SMS app with a message draft in place, and more. See https://developer.android.com/reference/kotlin/android/content/Intent?hl=en
37 | */
38 | sendIntent(
39 | action: string,
40 | extras?: Array<{ key: string; value: string | number | boolean }>
41 | ): Promise
42 | }
43 |
44 | export type StatusBarStyle = 'default' | 'light-content' | 'dark-content'
45 |
46 | /**
47 | * This exposes the native ToastAndroid module as a JS module. This has a function 'show'
48 | * which takes the following parameters:
49 | *
50 | * 1. String message: A string with the text to toast
51 | * 2. int duration: The duration of the toast. May be ToastAndroid.SHORT or ToastAndroid.LONG
52 | *
53 | * There is also a function `showWithGravity` to specify the layout gravity. May be
54 | * ToastAndroid.TOP, ToastAndroid.BOTTOM, ToastAndroid.CENTER
55 | */
56 | export interface ToastAndroidStatic {
57 | /**
58 | * String message: A string with the text to toast
59 | * int duration: The duration of the toast.
60 | * May be ToastAndroid.SHORT or ToastAndroid.LONG
61 | */
62 | show: (message: string, duration: number) => void
63 | /** `gravity` may be ToastAndroid.TOP, ToastAndroid.BOTTOM, ToastAndroid.CENTER */
64 | showWithGravity: (message: string, duration: number, gravity: number) => void
65 |
66 | showWithGravityAndOffset: (
67 | message: string,
68 | duration: number,
69 | gravity: number,
70 | xOffset: number,
71 | yOffset: number
72 | ) => void
73 | // Toast duration constants
74 | SHORT: number
75 | LONG: number
76 | // Toast gravity constants
77 | TOP: number
78 | BOTTOM: number
79 | CENTER: number
80 | }
81 |
82 | export interface VibrationStatic {
83 | vibrate(pattern?: number | number[] | null, repeat?: boolean | null): void
84 | /**
85 | * Stop vibration
86 | */
87 | cancel(): void
88 | }
89 |
--------------------------------------------------------------------------------
/packages/core/src/types/rn/net_info.ts:
--------------------------------------------------------------------------------
1 | export enum NetInfoStateType {
2 | unknown = 'unknown',
3 | none = 'none',
4 | cellular = 'cellular',
5 | wifi = 'wifi',
6 | bluetooth = 'bluetooth',
7 | ethernet = 'ethernet',
8 | wimax = 'wimax',
9 | vpn = 'vpn',
10 | other = 'other',
11 | }
12 | type NetInfoMethodType = 'HEAD' | 'GET'
13 | export enum NetInfoCellularGeneration {
14 | '2g' = '2g',
15 | '3g' = '3g',
16 | '4g' = '4g',
17 | '5g' = '5g',
18 | }
19 | interface NetInfoConnectedDetails {
20 | isConnectionExpensive: boolean
21 | }
22 | interface NetInfoConnectedState<
23 | T extends NetInfoStateType,
24 | D extends Record = Record
25 | > {
26 | type: T
27 | isConnected: true
28 | isInternetReachable: boolean | null
29 | details: D & NetInfoConnectedDetails
30 | isWifiEnabled?: boolean
31 | }
32 | interface NetInfoDisconnectedState {
33 | type: T
34 | isConnected: false
35 | isInternetReachable: false
36 | details: null
37 | }
38 | interface NetInfoUnknownState {
39 | type: NetInfoStateType.unknown
40 | isConnected: boolean | null
41 | isInternetReachable: null
42 | details: null
43 | }
44 | type NetInfoNoConnectionState = NetInfoDisconnectedState
45 | type NetInfoDisconnectedStates = NetInfoUnknownState | NetInfoNoConnectionState
46 | type NetInfoCellularState = NetInfoConnectedState<
47 | NetInfoStateType.cellular,
48 | {
49 | cellularGeneration: NetInfoCellularGeneration | null
50 | carrier: string | null
51 | }
52 | >
53 | type NetInfoWifiState = NetInfoConnectedState<
54 | NetInfoStateType.wifi,
55 | {
56 | ssid: string | null
57 | bssid: string | null
58 | strength: number | null
59 | ipAddress: string | null
60 | subnet: string | null
61 | frequency: number | null
62 | linkSpeed: number | null
63 | rxLinkSpeed: number | null
64 | txLinkSpeed: number | null
65 | }
66 | >
67 | type NetInfoBluetoothState = NetInfoConnectedState
68 | type NetInfoEthernetState = NetInfoConnectedState<
69 | NetInfoStateType.ethernet,
70 | {
71 | ipAddress: string | null
72 | subnet: string | null
73 | }
74 | >
75 | type NetInfoWimaxState = NetInfoConnectedState
76 | type NetInfoVpnState = NetInfoConnectedState
77 | type NetInfoOtherState = NetInfoConnectedState
78 | type NetInfoConnectedStates =
79 | | NetInfoCellularState
80 | | NetInfoWifiState
81 | | NetInfoBluetoothState
82 | | NetInfoEthernetState
83 | | NetInfoWimaxState
84 | | NetInfoVpnState
85 | | NetInfoOtherState
86 | type NetInfoState = NetInfoDisconnectedStates | NetInfoConnectedStates
87 | type NetInfoChangeHandler = (state: NetInfoState) => void
88 | type NetInfoSubscription = () => void
89 | interface NetInfoConfiguration {
90 | reachabilityUrl: string
91 | reachabilityMethod?: NetInfoMethodType
92 | reachabilityTest: (response: Response) => Promise
93 | reachabilityLongTimeout: number
94 | reachabilityShortTimeout: number
95 | reachabilityRequestTimeout: number
96 | reachabilityShouldRun: () => boolean
97 | shouldFetchWiFiSSID: boolean
98 | useNativeReachability: boolean
99 | }
100 |
101 | export interface NetInfo {
102 | configure: (configuration: Partial) => void
103 | fetch: (requestedInterface?: string) => Promise
104 | refresh: () => Promise
105 | addEventListener: (listener: NetInfoChangeHandler) => NetInfoSubscription
106 | useNetInfo: (configuration?: Partial) => NetInfoState
107 | }
108 |
--------------------------------------------------------------------------------
/packages/debug-tools/src/components/CopyableScript.tsx:
--------------------------------------------------------------------------------
1 | import { CHII_URL } from '@/utils'
2 | import React, { FC } from 'react'
3 | import useClipboard from 'react-use-clipboard'
4 | import Space from './Space'
5 |
6 | const targetSrc = (host = 'localhost') => `${CHII_URL}/target.js`
7 |
8 | const ScriptPart = ({ src }: { src: string }) => {
9 | const script = ``
10 | const [isCopied, setCopied] = useClipboard(script, {
11 | successDuration: 2000,
12 | })
13 | return (
14 | <>
15 |
16 | <script
17 |
18 | src
19 | =
20 | "
21 | {src}
22 | "
23 | ></script>
24 |
25 |
26 |
36 | >
37 | )
38 | }
39 |
40 | const ImportDebugPart = ({ src }: { src: string }) => {
41 | const script = `import debug from 'mincu-debug';\ndebug.connect();`
42 | const [isCopied, setCopied] = useClipboard(script, {
43 | successDuration: 2000,
44 | })
45 | return (
46 | <>
47 |
48 |
49 | import
50 |
51 | debug
52 |
53 | from
54 |
55 | '
56 | mincu-debug
57 | '
58 | ;
59 |
60 | {'\n'}
61 |
62 | debug
63 | .
64 | connect
65 | ()
66 | ;
67 |
68 |
69 |
70 |
80 | >
81 | )
82 | }
83 |
84 | const CopyableScript: FC<{
85 | ip: string
86 | }> = ({ ip }) => {
87 | const src = targetSrc(ip)
88 | return (
89 | <>
90 |
91 |
92 | 将 script 插入到你的页面
93 |
94 |
95 |
96 |
97 | 使用 mincu-debug 引入
98 |
99 |
100 |
101 |
111 | >
112 | )
113 | }
114 |
115 | export default CopyableScript
116 |
--------------------------------------------------------------------------------
/packages/demos/react-demo-shared/src/Modal.tsx:
--------------------------------------------------------------------------------
1 | import { Dialog, Transition } from '@headlessui/react'
2 | import { Fragment, useState } from 'react'
3 | import { useEffect } from 'react'
4 | import { Task } from 'tinybench'
5 | import 'twind/shim'
6 |
7 | interface Props {
8 | visible: boolean
9 | onClose?: () => void
10 | result?: Task['result']
11 | }
12 |
13 | const rn = (n: number) => Math.round(n)
14 |
15 | export default function BenchModal({ visible, onClose, result }: Props) {
16 | let [isOpen, setIsOpen] = useState(visible)
17 |
18 | useEffect(() => {
19 | setIsOpen(visible)
20 | }, [visible])
21 |
22 | function closeModal() {
23 | setIsOpen(false)
24 | onClose?.()
25 | }
26 |
27 | return (
28 | <>
29 |
30 |
101 |
102 | >
103 | )
104 | }
105 |
--------------------------------------------------------------------------------
/packages/debug/src/mincud/client.ts:
--------------------------------------------------------------------------------
1 | import { Encode } from 'console-feed-node-transform'
2 | import WebSocket, { MessageEvent } from 'isomorphic-ws'
3 | import { _window } from 'mincu-lib'
4 | import {
5 | CMD_DEV_TOOL,
6 | CMD_RELOAD,
7 | DEBUG_HOST,
8 | DEBUG_PORT,
9 | LogLevel,
10 | Received,
11 | DEBUG_CHII_PORT,
12 | } from 'mincu-lib/debug'
13 |
14 | const genReceived = (recv: Received) => {
15 | return JSON.stringify(recv)
16 | }
17 |
18 | export class Client {
19 | static KEY_DEV_TOOL = 'DEV_TOOL'
20 | private client: WebSocket
21 | private opened: boolean = false
22 |
23 | initChii() {
24 | var script = document.createElement('script')
25 | script.src = `${location.protocol}//${DEBUG_HOST}:${DEBUG_CHII_PORT}/target.js`
26 | document.body.appendChild(script)
27 | }
28 |
29 | init() {
30 | if (this.client || this.opened) return true
31 | try {
32 | this.client = new WebSocket(`ws://${DEBUG_HOST}:${DEBUG_PORT}`)
33 | if (this.client) {
34 | this.client.onerror = (e) => {
35 | console.error(e)
36 | this.opened = false
37 | }
38 | this.client.onopen = () => {
39 | this.opened = true
40 | this.log('info', `${_window.location?.origin} has connected`)
41 | }
42 | this.client.onmessage = this.bindServerCommand
43 | if (this.devToolActive()) {
44 | this.injectDevTool()
45 | }
46 | }
47 | } catch (error) {
48 | console.error(error)
49 | return false
50 | }
51 | return true
52 | }
53 |
54 | initByDebugTools() {
55 | if (this.client || this.opened) return true
56 | try {
57 | this.client = new WebSocket(`ws://${DEBUG_HOST}:${DEBUG_PORT}`)
58 | this.client.onopen = () => {
59 | this.opened = true
60 | this.log(
61 | 'info',
62 | `DebugTools at ${_window.location?.origin} has connected`
63 | )
64 | }
65 | this.client.onerror = () => {
66 | this.opened = false
67 | }
68 | } catch (error) {
69 | return false
70 | }
71 | return true
72 | }
73 |
74 | bindServerCommand = (event: MessageEvent) => {
75 | const { data } = event
76 | const cmd = data.toString()
77 | switch (cmd) {
78 | case CMD_RELOAD:
79 | _window.location?.reload()
80 | break
81 | case CMD_DEV_TOOL:
82 | this.toggleDevTool()
83 | break
84 | }
85 | }
86 |
87 | devToolActive() {
88 | return localStorage.getItem(Client.KEY_DEV_TOOL) === 'true'
89 | }
90 |
91 | toggleDevTool() {
92 | const active = this.devToolActive()
93 | if (!active) {
94 | this.injectDevTool()
95 | } else {
96 | _window.eruda?.destroy()
97 | }
98 | localStorage.setItem(Client.KEY_DEV_TOOL, String(!active))
99 | }
100 |
101 | /**
102 | * @description inject eruda console script
103 | * @see https://github.com/liriliri/eruda
104 | */
105 | injectDevTool() {
106 | const script = document.createElement('script')
107 | script.src = '//cdn.jsdelivr.net/npm/eruda'
108 | document.body.appendChild(script)
109 | script.onload = () => {
110 | _window.eruda?.init()
111 | }
112 | }
113 |
114 | /**
115 | * @description send log message to websocket server
116 | * @see https://github.com/facebook/metro/blob/master/packages/metro/src/HmrServer.js?#L211-L218
117 | * @note call console[level] in this function will cause maximum call stack error
118 | */
119 | log(level: LogLevel, ...args: any[]) {
120 | if (!this.client) {
121 | this.init()
122 | }
123 | if (!this.opened) {
124 | return
125 | }
126 | try {
127 | this.client.send(
128 | genReceived({
129 | type: 'log',
130 | level,
131 | data: Encode(args),
132 | })
133 | )
134 | } catch (err) {
135 | console.error(err)
136 | }
137 | }
138 |
139 | command(command: string, args: any[]) {
140 | if (this.opened) {
141 | this.client.send(
142 | genReceived({
143 | type: 'command',
144 | data: [command, ...args],
145 | })
146 | )
147 | return true
148 | }
149 | return false
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/packages/network/src/index.ts:
--------------------------------------------------------------------------------
1 | import mincuCore from 'mincu-core'
2 | import dataModule from 'mincu-data'
3 | import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
4 |
5 | type failedItem = {
6 | resolve: (value: unknown) => any
7 | reject: (value: unknown) => any
8 | }
9 |
10 | type ResToken = {
11 | data: {
12 | token: string
13 | }
14 | }
15 |
16 | export class NetWorkModule {
17 | private failedQueue: failedItem[] = []
18 | private isRefreshing = false
19 |
20 | public token: string = ''
21 |
22 | /**
23 | * @deprecated
24 | * networkModule.useAxiosInterceptors is for your need
25 | */
26 | public fetch: any
27 |
28 | static Instance() {
29 | return new NetWorkModule()
30 | }
31 |
32 | constructor() {
33 | this.token = dataModule.appData.user.token || ''
34 | }
35 |
36 | public axiosInterceptors = () => ({
37 | request: (config: AxiosRequestConfig) => {
38 | if (this.token) {
39 | config.headers.Authorization = this.getAuthorization(this.token)
40 | }
41 | return config
42 | },
43 | response: (response: AxiosResponse) => response,
44 | error: this.handleTokenExpired,
45 | })
46 |
47 | /**
48 | * @exmaple
49 | * const fetcher = axios.create()
50 | * networkModule.useAxiosInterceptors(fetcher)
51 | */
52 | public useAxiosInterceptors(axiosInstance: AxiosInstance) {
53 | const interceptors = this.axiosInterceptors()
54 | axiosInstance.interceptors.request.use(interceptors.request)
55 | axiosInstance.interceptors.response.use(
56 | interceptors.response,
57 | interceptors.error
58 | )
59 | }
60 |
61 | private setToken = (token: string) => {
62 | this.token = token
63 | }
64 |
65 | /**
66 | * @deprecated should not use
67 | */
68 | public getStoredToken() {}
69 |
70 | private getAuthorization(token: string) {
71 | return `passport ${token}`
72 | }
73 |
74 | /** 错误处理方法 */
75 | private handleTokenExpired = (error: any) => {
76 | const { response } = error
77 | const originalRequest = error?.config
78 |
79 | const mayExpired = response?.status === 401 || response?.status === 400
80 |
81 | if (mayExpired && !originalRequest._retry) {
82 | if (this.isRefreshing) {
83 | return new Promise((resolve, reject) => {
84 | this.failedQueue.push({ resolve, reject })
85 | })
86 | .then((token: string) => {
87 | originalRequest.headers['Authorization'] =
88 | this.getAuthorization(token)
89 | return originalRequest
90 | })
91 | .catch((err) => {
92 | return Promise.reject(err)
93 | })
94 | }
95 |
96 | originalRequest._retry = true
97 | this.isRefreshing = true
98 |
99 | return new Promise((resolve, reject) => {
100 | this.refreshToken()
101 | .then((token) => {
102 | originalRequest.headers['Authorization'] =
103 | this.getAuthorization(token)
104 | this.processQueue(null, token)
105 | resolve(originalRequest)
106 | })
107 | .catch((err) => {
108 | this.processQueue(err)
109 | reject(err)
110 | })
111 | .finally(() => {
112 | this.isRefreshing = false
113 | })
114 | })
115 | }
116 |
117 | return Promise.reject(error)
118 | }
119 |
120 | /** 处理错误请求队列 */
121 | private processQueue = (error: any, token = null) => {
122 | this.failedQueue.forEach((promise) => {
123 | if (error) {
124 | promise.reject(error)
125 | } else {
126 | promise.resolve(token)
127 | }
128 | })
129 |
130 | this.failedQueue = []
131 | }
132 |
133 | /**
134 | * 刷新 token 函数
135 | *
136 | * @returns 返回一个新 token 的 Promise 对象
137 | */
138 | public async refreshToken(): Promise {
139 | return new Promise((resolve) => {
140 | mincuCore.call('Auth', 'refreshToken', null, (res: ResToken) => {
141 | const token = res.data?.token
142 |
143 | /**重新刷新 token 缓存和内存 */
144 | this.setToken(token)
145 |
146 | /**传出 token */
147 | resolve(token ?? '')
148 | })
149 | })
150 | }
151 | }
152 |
153 | export default NetWorkModule.Instance()
154 |
--------------------------------------------------------------------------------
/packages/core/src/index.ts:
--------------------------------------------------------------------------------
1 | import { channelGenerator, EventMap } from './channel'
2 | import { FuncNames, INativeFuncs, AppData } from './interface'
3 | import { _window, noop } from 'mincu-lib'
4 | import { EventEmitter } from 'events'
5 |
6 | export * from './interface'
7 | export * from './channel'
8 |
9 | type ParamType = T extends (...args: infer U) => any ? U : never
10 | type CallReturnType = T extends (...args: any[]) => infer R ? R : T
11 |
12 | /**
13 | * 目前支持 web 和 native 的双向通信
14 | */
15 | export class MincuCoreBase {
16 | private eventKey: number
17 | private eventMap: EventMap
18 |
19 | constructor(eventKey?: number, eventMap?: EventMap) {
20 | this.eventKey = eventKey
21 | this.eventMap = eventMap
22 |
23 | channelGenerator(eventMap)
24 | }
25 |
26 | /**
27 | * 通过 userAgent 判断是否在 iNCU 环境
28 | * userAgent: iNCU.*
29 | */
30 | get isApp() {
31 | return _window?.navigator?.userAgent?.indexOf('iNCU') !== -1
32 | }
33 |
34 | /**
35 | * 与 App 端通信的消息通道
36 | */
37 | get messageChannel(): EventEmitter {
38 | return _window.RNMessageChannel
39 | }
40 |
41 | /**
42 | * 由 iNCU WebView 注入的来自 App 的数据
43 | */
44 | get appData(): AppData {
45 | return _window.appData
46 | }
47 |
48 | /**
49 | * App 端的 Webview JavaScriptInterface,用以向 App 端发送信息
50 | */
51 | get webview() {
52 | return _window.ReactNativeWebView
53 | }
54 |
55 | /**
56 | * 由 App 端注入的数据段,用以判断是否注入成功
57 | */
58 | get isReady() {
59 | return _window.appReady ?? false
60 | }
61 |
62 | initial = (
63 | resolve: (value?: unknown) => any,
64 | reject?: (value?: unknown) => any
65 | ) => {
66 | if (this.isReady) {
67 | resolve()
68 | return
69 | }
70 |
71 | // 轮询是否成功加载
72 | const scanner = setInterval(() => {
73 | if (this.isReady) {
74 | clearInterval(scanner)
75 | resolve()
76 | return
77 | }
78 | }, 50)
79 |
80 | // 5 秒超时
81 | setTimeout(() => {
82 | if (!this.isReady) {
83 | clearInterval(scanner)
84 | reject?.()
85 | }
86 | }, 5000)
87 | }
88 |
89 | /**
90 | * 添加一个原生事件监听器
91 | * */
92 | listener = (eventName: string, fn: (data) => any) => {
93 | return this.messageChannel?.on(`event-${eventName}`, fn)
94 | }
95 |
96 | /**
97 | * 添加一个原生事件监听器 (监听一次后立即销毁)
98 | * */
99 | once = (eventName: string, fn: (data) => any) => {
100 | return this.messageChannel?.once(`event-once-${eventName}`, fn)
101 | }
102 |
103 | /**
104 | * 移除某个原生事件监听器
105 | * */
106 | remove = (eventName: string, fn: (data) => any) => {
107 | this.messageChannel?.removeListener(`event-${eventName}`, fn)
108 | }
109 |
110 | /**
111 | * 主动请求并触发客户端事件
112 | */
113 | call = (
114 | baseClass: Class,
115 | method: Method,
116 | params: ParamType,
117 | success: (res?: {
118 | data: CallReturnType
119 | }) => any = noop,
120 | failed: (...args: any[]) => void = noop
121 | ) => {
122 | this.eventKey += 1
123 | this.eventMap[this.eventKey] = { success, failed }
124 |
125 | const data = {
126 | baseClass,
127 | method,
128 | params: params || [],
129 | key: this.eventKey,
130 | type: 'call',
131 | }
132 |
133 | this.webview?.postMessage(JSON.stringify(data))
134 | }
135 |
136 | callPromise = <
137 | Class extends FuncNames,
138 | Method extends keyof INativeFuncs[Class]
139 | >(
140 | baseClass: Class,
141 | method: Method,
142 | params: ParamType
143 | ) => {
144 | return new Promise>(
145 | (resolve, reject) => {
146 | this.call(
147 | baseClass,
148 | method,
149 | params,
150 | (res) => {
151 | resolve(res.data)
152 | },
153 | reject
154 | )
155 | }
156 | )
157 | }
158 |
159 | /**
160 | * Return a proxy handle callPromise from INativeFuncs
161 | */
162 | makeProxyFromNativeFunc = (func: Class) => {
163 | return new Proxy(
164 | {},
165 | {
166 | get: (_, prop: any) => {
167 | return (...args: any) =>
168 | this.callPromise(func, prop, [...args] as any)
169 | },
170 | }
171 | ) as any as INativeFuncs[Class]
172 | }
173 | }
174 |
175 | const mincuCore = new MincuCoreBase(0, {})
176 |
177 | export default mincuCore
178 |
--------------------------------------------------------------------------------
/packages/create/src/index.ts:
--------------------------------------------------------------------------------
1 | import path from 'path'
2 | import minimist from 'minimist'
3 | import { downloadWithCheck } from 'gdl'
4 | import {
5 | isEmpty,
6 | isValidPackageName,
7 | toValidPackageName,
8 | renameFiles,
9 | logSuccessTips,
10 | transformDeps,
11 | } from './utils'
12 | import fse from 'fs-extra'
13 | import prompts from 'prompts'
14 | import { cyan, red, green, lightMagenta, yellow } from 'kolorist'
15 |
16 | const cwd = process.cwd()
17 |
18 | interface Template {
19 | name: string
20 | description: string
21 | color: (str: string | number) => string
22 | }
23 |
24 | interface Result {
25 | projectName: string
26 | packageName?: string
27 | template: string
28 | overwriteChecker?: any
29 | overwrite?: boolean
30 | }
31 |
32 | const TEMPLATES: Template[] = [
33 | {
34 | name: 'react-vite',
35 | description: '推荐使用',
36 | color: cyan,
37 | },
38 | {
39 | name: 'ice-example',
40 | description: '非常好用',
41 | color: lightMagenta,
42 | },
43 | {
44 | name: 'react-next',
45 | description: '挺牛的',
46 | color: green,
47 | },
48 | {
49 | name: 'vanilla-ts',
50 | description: '纯纯原生',
51 | color: yellow,
52 | },
53 | ]
54 |
55 | const init = async () => {
56 | const argv = minimist(process.argv.slice(2), { string: ['_'] })
57 | let targetDir = argv._[0]
58 | const defaultProjectName = !targetDir ? 'mincu-project' : targetDir
59 |
60 | let template = argv.template || argv.t
61 |
62 | let result = {} as Result
63 |
64 | // input
65 | try {
66 | result = await prompts(
67 | [
68 | {
69 | type: targetDir ? null : 'text',
70 | name: 'projectName',
71 | message: '项目名称:',
72 | initial: defaultProjectName,
73 | onState: (state) =>
74 | (targetDir = state.value.trim() || defaultProjectName),
75 | },
76 | {
77 | type: () =>
78 | !fse.existsSync(targetDir) || isEmpty(targetDir) ? null : 'confirm',
79 | name: 'overwrite',
80 | message: () =>
81 | (targetDir === '.' ? '当前目录' : `目标目录 "${targetDir}"`) +
82 | ` 已存在. 删除已经存在的文件还是继续呢?`,
83 | },
84 | {
85 | type: (_, { overwrite } = { overwrite: false }) => {
86 | if (overwrite === false) {
87 | throw new Error(red('✖') + ' 操作已被取消')
88 | }
89 | return null
90 | },
91 | name: 'overwriteChecker',
92 | },
93 | {
94 | type: () => (isValidPackageName(targetDir) ? null : 'text'),
95 | name: 'packageName',
96 | message: 'package.json 的包名(packageName):',
97 | initial: () => toValidPackageName(targetDir),
98 | validate: (dir) =>
99 | isValidPackageName(dir) || '非法的 package.json 名',
100 | },
101 | {
102 | type:
103 | template && TEMPLATES.some((item) => template !== item.name)
104 | ? null
105 | : 'select',
106 | name: 'template',
107 | message:
108 | typeof template === 'string' &&
109 | !TEMPLATES.some((item) => template !== item.name)
110 | ? `"${template}" 并不是一个有效的模板. 请选择以上模板: `
111 | : '选择一个模板:',
112 | initial: 0,
113 | choices: TEMPLATES.map((item) => {
114 | return {
115 | title: item.color(`${item.name}: ${item.description}`),
116 | value: item.name,
117 | }
118 | }),
119 | },
120 | ],
121 | {
122 | onCancel: () => {
123 | throw new Error(red('✖') + ' 操作已被取消')
124 | },
125 | }
126 | )
127 | } catch (cancelled) {
128 | console.log(cancelled.message)
129 | return
130 | }
131 |
132 | // Package Path
133 | const root = path.join(cwd, targetDir)
134 |
135 | // Download template
136 | await downloadWithCheck(
137 | `https://github.com/ncuhome/mincu/tree/master/example/${result.template}`,
138 | root
139 | )
140 |
141 | // Rename files
142 | Object.keys(renameFiles).forEach((key) => {
143 | const oldPath = path.join(root, key)
144 | const newPath = path.join(root, renameFiles[key])
145 |
146 | if (!fse.existsSync(oldPath)) return
147 | fse.renameSync(oldPath, newPath)
148 | })
149 |
150 | // Write package.json
151 | const pkgPath = path.join(root, `package.json`)
152 | const pkg = fse.readJSONSync(pkgPath)
153 |
154 | pkg.name = result.packageName || targetDir
155 |
156 | transformDeps(pkg)
157 |
158 | fse.writeJSONSync(pkgPath, pkg, { spaces: 2 })
159 |
160 | logSuccessTips(targetDir, pkg)
161 | }
162 |
163 | init().catch((e) => {
164 | console.error(e)
165 | })
166 |
--------------------------------------------------------------------------------
/packages/core/src/types/rn/clipboard.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * `Clipboard` gives you an interface for setting and getting content from Clipboard on both iOS and Android
3 | */
4 | export interface Clipboard {
5 | /**
6 | * Get content of string type, this method returns a `Promise`, so you can use following code to get clipboard content
7 | * ```javascript
8 | * async _getContent() {
9 | * var content = await Clipboard.getString();
10 | * }
11 | * ```
12 | */
13 | getString(): Promise
14 | /**
15 | * Get clipboard image as PNG in base64, this method returns a `Promise`, so you can use following code to get clipboard content
16 | * ```javascript
17 | * async _getContent() {
18 | * var content = await Clipboard.getImagePNG();
19 | * }
20 | * ```
21 | */
22 | getImagePNG(): Promise
23 | /**
24 | * Get clipboard image as JPG in base64, this method returns a `Promise`, so you can use following code to get clipboard content
25 | * ```javascript
26 | * async _getContent() {
27 | * var content = await Clipboard.getImageJPG();
28 | * }
29 | * ```
30 | */
31 | getImageJPG(): Promise
32 | /**
33 | * Set content of base64 image type. You can use following code to set clipboard content
34 | * ```javascript
35 | * _setContent() {
36 | * Clipboard.setImage(...);
37 | * }
38 | *
39 | * iOS only
40 | * ```
41 | * @param the content to be stored in the clipboard.
42 | */
43 | setImage(content: string): void
44 | getImage(): Promise
45 | /**
46 | * Set content of string type. You can use following code to set clipboard content
47 | * ```javascript
48 | * _setContent() {
49 | * Clipboard.setString('hello world');
50 | * }
51 | * ```
52 | * @param the content to be stored in the clipboard.
53 | */
54 | setString(content: string): void
55 | /**
56 | * Returns whether the clipboard has content or is empty.
57 | * This method returns a `Promise`, so you can use following code to get clipboard content
58 | * ```javascript
59 | * async _hasContent() {
60 | * var hasContent = await Clipboard.hasString();
61 | * }
62 | * ```
63 | */
64 | hasString(): any
65 | /**
66 | * Returns whether the clipboard has an image or is empty.
67 | * This method returns a `Promise`, so you can use following code to check clipboard content
68 | * ```javascript
69 | * async _hasContent() {
70 | * var hasContent = await Clipboard.hasImage();
71 | * }
72 | * ```
73 | */
74 | hasImage(): any
75 | /**
76 | * (IOS Only)
77 | * Returns whether the clipboard has a URL content. Can check
78 | * if there is a URL content in clipboard without triggering PasteBoard notification for iOS 14+
79 | * This method returns a `Promise`, so you can use following code to check for url content in clipboard.
80 | * ```javascript
81 | * async _hasURL() {
82 | * var hasURL = await Clipboard.hasURL();
83 | * }
84 | * ```
85 | */
86 | hasURL(): any
87 | /**
88 | * (IOS 14+ Only)
89 | * Returns whether the clipboard has a Number(UIPasteboardDetectionPatternNumber) content. Can check
90 | * if there is a Number content in clipboard without triggering PasteBoard notification for iOS 14+
91 | * This method returns a `Promise`, so you can use following code to check for Number content in clipboard.
92 | * ```javascript
93 | * async _hasNumber() {
94 | * var hasNumber = await Clipboard.hasNumber();
95 | * }
96 | * ```
97 | */
98 | hasNumber(): any
99 | /**
100 | * (IOS 14+ Only)
101 | * Returns whether the clipboard has a WebURL(UIPasteboardDetectionPatternProbableWebURL) content. Can check
102 | * if there is a WebURL content in clipboard without triggering PasteBoard notification for iOS 14+
103 | * This method returns a `Promise`, so you can use following code to check for WebURL content in clipboard.
104 | * ```javascript
105 | * async _hasWebURL() {
106 | * var hasWebURL = await Clipboard.hasWebURL();
107 | * }
108 | * ```
109 | */
110 | hasWebURL(): any
111 | /**
112 | * (iOS and Android Only)
113 | * Adds a listener to get notifications when the clipboard has changed.
114 | * If this is the first listener, turns on clipboard notifications on the native side.
115 | * It returns EmitterSubscription where you can call "remove" to remove listener
116 | * ```javascript
117 | * const listener = () => console.log("changed!");
118 | * Clipboard.addListener(listener);
119 | * ```
120 | */
121 | addListener(callback: () => void): {
122 | remove: () => void
123 | }
124 | /**
125 | * (iOS and Android Only)
126 | * Removes all previously registered listeners and turns off notifications on the native side.
127 | * ```javascript
128 | * Clipboard.removeAllListeners();
129 | * ```
130 | */
131 | removeAllListeners(): void
132 | }
133 |
--------------------------------------------------------------------------------
/packages/debug/src/mincud/openBrowser.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | *
4 | * This source code is licensed under the MIT license found in the
5 | * LICENSE file in the root directory of this source tree.
6 | */
7 |
8 | var chalk = require('chalk')
9 | var execSync = require('child_process').execSync
10 | var spawn = require('cross-spawn')
11 | var open = require('open')
12 |
13 | // https://github.com/sindresorhus/open#app
14 | var OSX_CHROME = 'google chrome'
15 |
16 | const Actions = Object.freeze({
17 | NONE: 0,
18 | BROWSER: 1,
19 | SCRIPT: 2,
20 | })
21 |
22 | function getBrowserEnv() {
23 | // Attempt to honor this environment variable.
24 | // It is specific to the operating system.
25 | // See https://github.com/sindresorhus/open#app for documentation.
26 | const value = process.env.BROWSER
27 | const args = process.env.BROWSER_ARGS
28 | ? process.env.BROWSER_ARGS.split(' ')
29 | : []
30 | let action
31 | if (!value) {
32 | // Default.
33 | action = Actions.BROWSER
34 | } else if (value.toLowerCase().endsWith('.js')) {
35 | action = Actions.SCRIPT
36 | } else if (value.toLowerCase() === 'none') {
37 | action = Actions.NONE
38 | } else {
39 | action = Actions.BROWSER
40 | }
41 | return { action, value, args }
42 | }
43 |
44 | function executeNodeScript(scriptPath, url) {
45 | const extraArgs = process.argv.slice(2)
46 | const child = spawn(process.execPath, [scriptPath, ...extraArgs, url], {
47 | stdio: 'inherit',
48 | })
49 | child.on('close', (code) => {
50 | if (code !== 0) {
51 | console.log()
52 | console.log(
53 | chalk.red(
54 | 'The script specified as BROWSER environment variable failed.'
55 | )
56 | )
57 | console.log(chalk.cyan(scriptPath) + ' exited with code ' + code + '.')
58 | console.log()
59 | return
60 | }
61 | })
62 | return true
63 | }
64 |
65 | function startBrowserProcess(browser, url, args) {
66 | // If we're on OS X, the user hasn't specifically
67 | // requested a different browser, we can try opening
68 | // Chrome with AppleScript. This lets us reuse an
69 | // existing tab when possible instead of creating a new one.
70 | const shouldTryOpenChromiumWithAppleScript =
71 | process.platform === 'darwin' &&
72 | (typeof browser !== 'string' || browser === OSX_CHROME)
73 |
74 | if (shouldTryOpenChromiumWithAppleScript) {
75 | // Will use the first open browser found from list
76 | const supportedChromiumBrowsers = [
77 | 'Google Chrome Canary',
78 | 'Google Chrome',
79 | 'Microsoft Edge',
80 | 'Brave Browser',
81 | 'Vivaldi',
82 | 'Chromium',
83 | ]
84 |
85 | for (let chromiumBrowser of supportedChromiumBrowsers) {
86 | try {
87 | // Try our best to reuse existing tab
88 | // on OSX Chromium-based browser with AppleScript
89 | execSync('ps cax | grep "' + chromiumBrowser + '"')
90 | execSync(
91 | 'osascript openChrome.applescript "' +
92 | encodeURI(url) +
93 | '" "' +
94 | chromiumBrowser +
95 | '"',
96 | {
97 | cwd: __dirname,
98 | stdio: 'ignore',
99 | }
100 | )
101 | return true
102 | } catch (err) {
103 | // Ignore errors.
104 | }
105 | }
106 | }
107 |
108 | // Another special case: on OS X, check if BROWSER has been set to "open".
109 | // In this case, instead of passing `open` to `opn` (which won't work),
110 | // just ignore it (thus ensuring the intended behavior, i.e. opening the system browser):
111 | // https://github.com/facebook/create-react-app/pull/1690#issuecomment-283518768
112 | if (process.platform === 'darwin' && browser === 'open') {
113 | browser = undefined
114 | }
115 |
116 | // If there are arguments, they must be passed as array with the browser
117 | if (typeof browser === 'string' && args.length > 0) {
118 | browser = [browser].concat(args)
119 | }
120 |
121 | // Fallback to open
122 | // (It will always open new tab)
123 | try {
124 | var options = { app: browser, wait: false, url: true }
125 | open(url, options).catch(() => {}) // Prevent `unhandledRejection` error.
126 | return true
127 | } catch (err) {
128 | return false
129 | }
130 | }
131 |
132 | /**
133 | * Reads the BROWSER environment variable and decides what to do with it. Returns
134 | * true if it opened a browser or ran a node.js script, otherwise false.
135 | */
136 | function openBrowser(url: string) {
137 | const { action, value, args } = getBrowserEnv()
138 | switch (action) {
139 | case Actions.NONE:
140 | // Special case: BROWSER="none" will prevent opening completely.
141 | return false
142 | case Actions.SCRIPT:
143 | return executeNodeScript(value, url)
144 | case Actions.BROWSER:
145 | return startBrowserProcess(value, url, args)
146 | default:
147 | throw new Error('Not implemented.')
148 | }
149 | }
150 |
151 | export default openBrowser
152 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Mincu 南大家园 JS API
2 |
3 | ## 文档地址
4 |
5 |
6 |
7 | ## 什么是 Mincu?
8 |
9 | iNCU 为其内嵌的 WEB 页面提供了丰富的 JS API,用来扩展内嵌页面 JS 的能力,如获取用户信息、操作原生 UI、获取原生 UI 和数据调用能力,以及解决你最头疼的认证系统。
10 |
11 | ## 为什么要用?
12 |
13 | 1. 定制属于你的 webview,做最极致的用户体验
14 |
15 | 2. 无需再为调试客户端头疼,使用 Web 开发技术即可获得和 Native 一样的体验
16 |
17 | 3. 跨平台调用原生能力
18 |
19 | 4. 可唤起系统原生的 UI 界面/组件,让 Web App 更 Native 化
20 |
21 | 5. 使用客户端分享功能,打通用户分享转发链路
22 |
23 | ## 迭代计划
24 |
25 | 1. 集成更多原生功能
26 |
27 | 2. useNativeState 状态缓存
28 |
29 | 3. 高效调试方案
30 |
31 | 4. 脚手架能力 (@Dollie)
32 |
33 | 5. 考虑将原生代码同样集成于本仓库
34 |
35 | 6. 白名单系统
36 |
37 | 7. ...
38 |
39 | ## 使用说明
40 |
41 | ### Quick Start
42 |
43 | 快速创建 mincu 项目:
44 |
45 | ```sh
46 | # npm
47 | $ npm init mincu@latest
48 | # yarn
49 | $ yarn create mincu
50 | # pnpm
51 | $ pnpm create mincu
52 | # or
53 | $ npx create-mincu
54 | ```
55 |
56 | ### 安装依赖
57 |
58 | #### React
59 |
60 | ```sh
61 | $ npm install mincu-react
62 | # or
63 | $ yarn add mincu-react
64 | ```
65 |
66 | #### 其他 (Vue、Vanilla)
67 |
68 | ```cmd
69 | $ npm install mincu-vanilla
70 | # or
71 | $ yarn add mincu-vanilla
72 | ```
73 |
74 | ### 引入
75 |
76 | ```jsx
77 | import { useLogin } from 'mincu-react' // or mincu-hooks
78 |
79 | const App = () => {
80 | // 使用 App 端登录并获取是否初始化 Web 容器状态
81 | // useLogin 是一个组合 hook
82 | // 里面包含 useAppReady 和登录状态获取并存储的逻辑
83 | const { isReady } = useLogin()
84 |
85 | if (!isReady) {
86 | return Loading
87 | }
88 |
89 | return Thank you for using mincu
90 | }
91 | ```
92 |
93 | ### 接收 Native -> Web 通信方法
94 |
95 | ```jsx
96 | import { useNativeState } from 'mincu-react' // or mincu-hooks
97 |
98 | const App = () => {
99 | // 已初始化
100 |
101 | // 使用 Native 对 Web 的通信实现颜色主题状态共享
102 | // 接收 Native 端已注册的可共享状态的变化
103 | const colorScheme = useNativeState('colorScheme')
104 |
105 | return Current Theme is {colorScheme}
106 | }
107 | ```
108 |
109 | ### Web -> Native 通信方法
110 |
111 | 这种方法更加常用一些
112 |
113 | ```jsx
114 | import { networkModule } from 'mincu-react' // or mincu-network
115 |
116 | const App = () => {
117 | // 已初始化
118 |
119 | const refreshToken = async () => {
120 | // 向 Native 通信,并获取 Native 端的返回值
121 | const token = await networkModule.refreshToken()
122 | alert(token)
123 | }
124 |
125 | return
126 | }
127 | ```
128 |
129 | ### 调试方法
130 |
131 | 为了方便在移动端 WebView 中调试,我们提供了 `mincu-debug` ,`mincu-debug` 采用了 Client/Server 模型,实现了各种在 WebView 中打 log,刷新页面,注入/取消注入 Devtool 等功能。(参考 react-native 的 HMRClient/Server)。
132 |
133 | - 安装 `mincu-debug`
134 |
135 | ```cmd
136 | npm i --save-dev mincu-debug # or yarn add -D mincu-debug
137 | ```
138 |
139 | - 在前端代码中引入 Client,通过 applyConsole 方法来重写默认的 console 事件,实现打印事件的绑定。建议只在 dev 环境中动态引入,避免增大 bundle 体积。
140 |
141 | ```js
142 | // 如果你使用 vite,则通过 import.meta.env.DEV 判断 DEV 环境。
143 | if (process.env.NODE_ENV === 'development') {
144 | import('mincu-debug').then(({ default: debugModule }) => {
145 | debugModule.applyConsole()
146 | })
147 | }
148 | ```
149 |
150 | - 启动 `mincud` Server,监听来自 Client 的打印事件:
151 |
152 | ```cmd
153 | npx mincud
154 | ```
155 |
156 | 推荐将 `mincud` 与前端 dev server 同时启动,不需要额外开启另外一个终端:
157 |
158 | ```cmd
159 | npx mincud npm run dev
160 | ```
161 |
162 | ```json
163 | // package.json
164 | {
165 | "scripts": {
166 | "start": "mincud npm run dev",
167 | "dev": "vite --host",
168 | "build": "tsc && vite build",
169 | "serve": "vite preview"
170 | }
171 | }
172 | ```
173 |
174 | - 执行命令 `npm run start` 后,`mincud` 将会启动并执行后面的 `npm run dev` 命令,然后对该命令执行的结果进行相应操作,对目标命令的输出结果匹配,匹配到 dev host(比如 )后将会打开一个二维码页面,这时打开南大家园,在生活 Tab,打开右上角 - 扫一扫页面进行扫描即可在南大家园内跳转到该页面进行开发。
175 |
176 | - mincud 启动后将会捕获终端输入事件,按 `r` 会尝试刷新页面,按 `d` 则会尝试切换(注入/取消注入)Devtool([eruda](https://github.com/liriliri/eruda))
177 |
178 | ```cmd
179 | > Press "r" | Reload the client page
180 | > Press "d" | Toggle the client devtool
181 | ```
182 |
183 | 完整的用法请看 [example/vanilla-ts](./example/vanilla-ts)
184 |
185 | ## 其他说明
186 |
187 | ### packages
188 |
189 | - mincu-core
190 | 核心逻辑部分,包含了常用的用户数据,提供 web 和 native 的双向通信、调用来自 App 的接口等功能。
191 | - mincu-data
192 | 数据部分,基本上来自于 core 里的 appData,不过加了一层初始化默认值处理。
193 | - mincu-debug
194 | 调试部分,包含了 mincud 和 debugModule,以方便在 WebView 中进行远程调试。
195 | - mincu-event
196 | 封装了一些原生操作函数,包括 openUrl, setShareConfig, showShare, login。
197 | - mincu-hooks
198 | 封装了一些适用于 react 的 hooks,包括 useAppReady, useNativeState, useSafeArea。
199 | - mincu-lib
200 | 共享库,包含了 constant 及 utils。
201 | - mincu-network
202 | 基于 axios 封装的网络库,主要增加了请求拦截器,刷新 token 等功能。
203 | - mincu-ui
204 | 封装了与原生界面显示有关的调用,包括 Toast, StatusBar Style, Header 标题栏, toScreen 跳转, exit 退出。
205 | - create-mincu
206 | mincu 模板生成 cli,开箱即用。
207 |
208 | ### presets
209 |
210 | - mincu-vanilla
211 | 依赖了 mincu-core, mincu-data, mincu-event, mincu-network, mincu-ui
212 | - mincu-react
213 | 依赖了 mincu-vanilla, mincu-hooks
214 |
215 | 它们都可以单独地引入到你的项目中使用。你可以根据你的需求引入所需要的依赖。
216 |
217 | ## 使用到的项目
218 |
219 | - 返校报到(学生端)- [ncuhome/back-home](https://github.com/ncuhome/back-home)
220 | - 家园工作室秋季新生招新页面 - [ncuhome/hr2019_fe_to_fresher](https://github.com/ncuhome/hr2019_fe_to_fresher/)
221 |
--------------------------------------------------------------------------------
/example/vue-vite/src/Home.vue:
--------------------------------------------------------------------------------
1 |
120 |
121 |
122 |
123 |
124 |
125 | 学号: {{ studentId }}
126 |
127 |
128 | 主题色: {{ colorScheme }}
129 |
130 |
133 |
134 |
135 |
136 |
137 |
138 |
导航
139 |
142 |
150 |
153 |
156 |
157 |
158 |
159 |
162 |
165 |
166 |
169 |
170 |
colors 测试
171 |
174 | colors.white
175 |
176 |
179 | colors.black
180 |
181 |
182 |
MincuStorage 测试
183 |
184 |
187 |
188 |
189 |
190 |
191 |
192 |
--------------------------------------------------------------------------------