-
Notifications
You must be signed in to change notification settings - Fork 19.8k
fix: theme-switch-keep-data. close apache#21200 #21201
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
8575bb1
6c4ba79
2565079
ebd26ff
f72bb3f
03e13c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -249,7 +249,7 @@ class GlobalModel extends Model<ECUnitOption> { | |
} | ||
|
||
private _resetOption( | ||
type: 'recreate' | 'timeline' | 'media', | ||
type: 'recreate' | 'timeline' | 'media' | 'theme', | ||
opt: InnerSetOptionOpts | ||
): boolean { | ||
let optionChanged = false; | ||
|
@@ -283,6 +283,13 @@ class GlobalModel extends Model<ECUnitOption> { | |
// If we really need to modify a props in each `MediaUnit['option']`, use the full version | ||
// (`{baseOption, media}`) in `setOption`. | ||
// For `timeline`, the case is the same. | ||
if (type === 'theme') { | ||
const themeOption = this._theme.option; | ||
if (themeOption) { | ||
mergeTheme(this.option, themeOption, true); | ||
optionChanged = true; | ||
} | ||
} | ||
|
||
if (!type || type === 'recreate' || type === 'timeline') { | ||
const timelineOption = optionManager.getTimelineOption(this); | ||
|
@@ -321,7 +328,6 @@ class GlobalModel extends Model<ECUnitOption> { | |
const replaceMergeMainTypeMap = opt && opt.replaceMergeMainTypeMap; | ||
|
||
resetSourceDefaulter(this); | ||
|
||
// If no component class, merge directly. | ||
// For example: color, animaiton options, etc. | ||
each(newOption, function (componentOption, mainType: ComponentMainType) { | ||
|
@@ -547,7 +553,7 @@ echarts.use([${seriesImportName}]);`); | |
|
||
setTheme(theme: object) { | ||
this._theme = new Model(theme); | ||
this._resetOption('recreate', null); | ||
this._resetOption('theme', null); | ||
} | ||
|
||
getTheme(): Model { | ||
|
@@ -1011,7 +1017,7 @@ function isNotTargetSeries(seriesModel: SeriesModel, payload: Payload): boolean | |
} | ||
} | ||
|
||
function mergeTheme(option: ECUnitOption, theme: ThemeOption): void { | ||
function mergeTheme(option: ECUnitOption, theme: ThemeOption, preserveUserOptions?: boolean): void { | ||
// PENDING | ||
// NOT use `colorLayer` in theme if option has `color` | ||
const notMergeColorLayer = option.color && !option.colorLayer; | ||
|
@@ -1029,7 +1035,9 @@ function mergeTheme(option: ECUnitOption, theme: ThemeOption): void { | |
if (typeof themeItem === 'object') { | ||
option[name] = !option[name] | ||
? clone(themeItem) | ||
: merge(option[name], themeItem, false); | ||
: preserveUserOptions | ||
? merge(themeItem, option[name], false) // User options have higher priority | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Theoretically "changing theme and keep the currently state" requires a big refactor: introduce a extra underlying model into the model cascade to accommodate theme option, which can be replaced in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So it seems that if we need to solve this problem now, there are two options: either do it the way I did in my first fix commit: 8575bb1, that is, keep the configuration first, then apply it after changing the theme, or we would really have to carry out a significant amount of refactoring work. Currently, my proposed solutions are:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently, I think the quick fix proposed should not be applied, since it brings more bugs that cannot to be fixed.
Could you explain the original scenario where you need to use setTheme while keeping data? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The most basic requirement comes from this issue(#21200 ) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm afraid issue(#21200 ) is not a basic requirement. It does not mention why we need use the API like that in a real-world scenario. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Upon seeing this topic, my thoughts are about how the system's theme switching could be used in this way. However, it also seems reasonable to expect that after switching the theme, the previous settings should remain consistent. |
||
: merge(option[name], themeItem, false); // Theme has higher priority | ||
} | ||
else { | ||
if (option[name] == null) { | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The format of the
theme object
is different from theoption
, and currently all of the theme are applied byComponent#mergeDefaultAndTheme
, therefore,theme object
should not be the input ofthis._mergeOption
.From my understanding, under the current definition, the implementation of this feature (keep the previous changes when
setTheme
) is unfeasible.The current definition is:
theme
acts as "default values", andoption
can override properties specified in atheme
, but not vice versa.Suppose we simply merge a new theme to the current model, some bad cases probably arise, for example:
theme1
bysetTheme
option1
bysetOption
theme2
bysetTheme
option2
bysetOption
Some properties specified by
option1
may be overridden bytheme2
, which is unexpected.Once we introduce that bad cases, they are unable to be fixed and cause the behavior unpredictable and error-prone.
If implement this feature by saving all of the inputs to the API (
setOption
,dispatchAction
, etc.), and restore them when callingsetTheme
, that might be logically correct, but may significantly degrade performance, and cause memory leak in scenarios thatsetOption
is called repeatedly over time.I'm not quite sure the real-world scenarios that requires "
setTheme
while keeping data". Is there any alternative way to achieve that?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.