Skip to content

Commit

Permalink
Fix Flow typing for Mithril, fix #3359
Browse files Browse the repository at this point in the history
  • Loading branch information
charlag authored and johnbotris committed Aug 10, 2021
1 parent a6ed5b2 commit eb9cd87
Show file tree
Hide file tree
Showing 22 changed files with 253 additions and 165 deletions.
2 changes: 2 additions & 0 deletions buildSrc/RollupConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ export const babelPlugins = [
// We technically don't need to have this as we expect async to just work but we rely on bluebird in many places and native async
// doesn't care about us redefining global Promise.
"@babel/plugin-transform-async-to-generator",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
]
export const babelDesktopPlugins = [
// Using Flow plugin and not preset to run before class-properties and avoid generating strange property code
Expand Down
3 changes: 1 addition & 2 deletions flow/libs.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,14 +267,13 @@ declare class ContactFindOptions { // cordova contact plugin
}

interface Attributes {

[key: string]: any;
}

type $Attrs<+T> = $ReadOnly<T>

// Declared at the top level to not import it in all places
interface MComponent<+Attrs> extends Lifecycle<Attrs> {
interface MComponent<-Attrs> extends Lifecycle<Attrs> {
/** Creates a view out of virtual elements. */
view(vnode: Vnode<Attrs>): Children;
}
Expand Down
119 changes: 119 additions & 0 deletions package-lock.json

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

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"type": "module",
"scripts": {
"flow": "flow; test $? -eq 0 -o $? -eq 2",
"flow": "flow --show-all-branches; test $? -eq 0 -o $? -eq 2",
"start": "./start-desktop.sh",
"test": "cd test && node --icu-data-dir=../node_modules/full-icu test api -c && node --icu-data-dir=../node_modules/full-icu test client",
"testapi": "cd test && node --icu-data-dir=../node_modules/full-icu test api",
Expand All @@ -33,6 +33,8 @@
"@babel/plugin-proposal-object-rest-spread": "7.3.4",
"@babel/plugin-syntax-dynamic-import": "7.8.3",
"@babel/plugin-transform-async-to-generator": "7.13.0",
"@babel/plugin-proposal-optional-chaining": "^7.14.5",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5",
"@babel/preset-flow": "7.14.5",
"@rollup/plugin-babel": "5.3.0",
"@rollup/plugin-commonjs": "16.0.0",
Expand Down
2 changes: 1 addition & 1 deletion src/gui/base/DropDownSelectorN.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export type DropDownSelectorAttrs<T> = {
* The handler is invoked with the new selected value. The displayed selected value is not changed automatically,
* but the handler is responsible for updating this DropDownSelector. The value is updated immediately, if no selectionChangedHandler is provided
*/
selectionChangedHandler?: handler<T>,
selectionChangedHandler?: ?handler<T>,
helpLabel?: lazy<Children>,
dropdownWidth?: number,
icon?: AllIconsEnum,
Expand Down
8 changes: 4 additions & 4 deletions src/gui/base/DropdownN.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export type DropdownInfoAttrs = {
/**
* Renders small info message inside the dropdown.
*/
const DropdownInfo = pureComponent(({center, bold, info}: DropdownInfoAttrs) => {
const DropdownInfo = pureComponent<DropdownInfoAttrs>(({center, bold, info}) => {
return m(".dropdown-info.text-break.selectable" + (center ? ".center" : "") + (bold ? ".b" : ""), info)
})

Expand Down Expand Up @@ -158,11 +158,11 @@ export class DropdownN {
},
this._visibleChildren().map(child => {
if (isDropDownInfo(child)) {
return m(DropdownInfo, child)
return m(DropdownInfo, downcast<DropdownInfoAttrs>(child))
} else if (typeof child.href === 'undefined') {
return m(ButtonN, ((child: any): ButtonAttrs))
return m(ButtonN, downcast<ButtonAttrs>(child))
} else {
return m(NavButtonN, ((child: any): NavButtonAttrs))
return m(NavButtonN, downcast<NavButtonAttrs>(child))
}
}))
}
Expand Down
22 changes: 9 additions & 13 deletions src/gui/base/InfoBanner.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import m from "mithril"
import {theme} from "../theme"
import type {InfoLink, TranslationKey} from "../../misc/LanguageViewModel"
import {lang} from "../../misc/LanguageViewModel"
import type {ButtonAttrs} from "./ButtonN"
import {ButtonN, ButtonType} from "./ButtonN"
import {NavButtonN} from "./NavButtonN"
import {mapNullable} from "../../api/common/utils/Utils"
Expand All @@ -21,17 +22,12 @@ export const BannerType = Object.freeze({

type BannerTypeEnum = $Values<typeof BannerType>

// Compatible with ButtonAttrs
export type BannerButtonParams = {
label: TranslationKey | lazy<string>,
click: () => mixed,
}
export type InfoBannerAttrs = {
message: TranslationKey | lazy<string>,
icon: AllIconsEnum,
helpLink?: ?InfoLink,
buttons?: ?$ReadOnlyArray<?BannerButtonParams>,
type: BannerTypeEnum
buttons?: ?$ReadOnlyArray<?ButtonAttrs>,
type?: BannerTypeEnum
}

/**
Expand Down Expand Up @@ -69,7 +65,7 @@ export class InfoBanner implements MComponent<InfoBannerAttrs> {
])
}

renderIcon(icon: AllIconsEnum, type: BannerTypeEnum): Children {
renderIcon(icon: AllIconsEnum, type: ?BannerTypeEnum): Children {
return m(Icon, {
icon,
style: {
Expand All @@ -79,11 +75,10 @@ export class InfoBanner implements MComponent<InfoBannerAttrs> {
})
}

renderButtons(buttons: $ReadOnlyArray<?BannerButtonParams>): Children {
return buttons.filter(Boolean).map(({label, click}) => m(ButtonN, {
label,
renderButtons(buttons: $ReadOnlyArray<?ButtonAttrs>): Children {
return buttons.filter(Boolean).map((attrs) => m(ButtonN, {
...attrs,
type: ButtonType.Secondary,
click,
}))
}

Expand All @@ -95,7 +90,8 @@ export class InfoBanner implements MComponent<InfoBannerAttrs> {
href: lang.getInfoLink(helpLink),
small: true,
hideLabel: true,
centred: true
centred: true,
label: "help_label"
}))
}
}
4 changes: 3 additions & 1 deletion src/gui/base/NotificationOverlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ class NotificationOverlay implements MComponent<NotificationOverlayAttrs> {
}

/**
* @param message What will be shown inside notification
* @param closeButtonAttrs To define the close button in the notification
* @param buttons The postpone button is automatically added and does not have to be passed from outside
*/
export function show(message: MComponent<mixed>, closeButtonAttrs: $Shape<ButtonAttrs>, buttons: Array<ButtonAttrs>) {
export function show(message: MComponent<void>, closeButtonAttrs: $Shape<ButtonAttrs>, buttons: Array<ButtonAttrs>) {
notificationQueue.push({message, buttons, closeButtonAttrs})
if (notificationQueue.length > 1) {
// another notification is already visible. Next notification will be shown when closing current notification
Expand Down
Loading

0 comments on commit eb9cd87

Please sign in to comment.