Last active
January 18, 2018 08:01
-
-
Save dam0vm3nt/d50b4862ccfdacd91d11 to your computer and use it in GitHub Desktop.
Auto notify support for new polymer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import "package:polymer/polymer.dart"; | |
import "package:observe/observe.dart"; | |
import "package:smoke/smoke.dart"; | |
import "package:logging/logging.dart"; | |
class ObservablePolymerNotifier { | |
static final Logger _logger = new Logger("polymer.auto.notify"); | |
String _path=""; | |
PolymerElement _element; | |
Observable _target; | |
StreamSubscription _sub; | |
Map<String,ObservablePolymerNotifier> _subNotifiers = {}; | |
ObservablePolymerNotifier(PolymerElement element, var target,[String path=""]) { | |
_element = element; | |
_path = path; | |
_target = target; | |
if (target is Observable) { | |
_sub = target.changes.listen((List<ChangeRecord> recs) { | |
recs.where((ChangeRecord cr) => cr is PropertyChangeRecord).forEach((PropertyChangeRecord pcr) { | |
var val = pcr.newValue; | |
_notifySymbol(symbolToName(pcr.name), val); | |
}); | |
}); | |
} else if (target is ObservableList) { | |
_sub = (target as ObservableList).listChanges.listen((List<ListChangeRecord> rc){ | |
// Notify splice | |
rc.forEach((ListChangeRecord lc) { | |
_notifySplice(target,"${_path}${symbolToName(pcr.name)}",lc.index,lc.addedCount,lc.removed); | |
// Fix observers | |
if(lc.removed!=null) { | |
for(int i=0;i<lc.removed.length;i++) { | |
_subNotifiers.remove((lc.index+i).toString()).close(); | |
} | |
// fix path on the rest | |
for (int i=lc.index;i<target.length;i++) { | |
_subNotifiers[i.toString()]=_subNotifiers.remove((i+lc.removed.length).toString()) | |
.._path="${_path}${symbolToName(pcr.name)}.${i}"; | |
} | |
} | |
if (lc.addedCount>0) { | |
// Fix path on tail | |
for (int i=lc.index+lc.addedCount;i<target.length;i++) { | |
_subNotifiers[i.toString()] =_subNotifiers.remove((i-lc.addedCount).toString()) | |
.._path="${_path}${symbolToName(pcr.name)}.${i}"; | |
} | |
// Add new observers | |
for (int i=lc.index;i<lc.addedCount+lc.index;i++) { | |
_notifySymbol(i.toString(),target[i]); | |
} | |
} | |
}); | |
}); | |
} | |
// Add Sub | |
if (target is List) { | |
for (int i=0;i<target.length;i++) { | |
_notifySplice(target,"${_path}".substring(0,_path.length-1),0,target.length,[]); | |
_notifySymbol(i.toString(),target[i]); | |
} | |
} else { | |
List<Declaration> fields = query(target.runtimeType,new QueryOptions(includeFields:true,includeProperties:true,includeInherited:false)); | |
fields.forEach((Declaration f) { | |
if (f.annotations.any((a)=> a is ObservableProperty)) { | |
var fieldValue=read(target,f.name); | |
_notifySymbol(symbolToName(f.name),fieldValue); | |
} | |
}); | |
} | |
} | |
void _notifySymbol(String name,var value) { | |
String path = "${_path}${name}"; | |
_logger.fine("Notify ${path} with ${value} for ${_element}"); | |
_element.notifyPath(path,value); | |
_installSubNotifier(name,value); | |
} | |
void _installSubNotifier(String name,var target) { | |
// Attach a new sub notifier for observable objects | |
_logger.fine("Installing subnotifier for ${name} with ${target}"); | |
ObservablePolymerNotifier subNotifier = _subNotifiers[name]; | |
if (subNotifier!=null) { | |
subNotifier.close(); | |
} | |
String subPath = "${_path}${name}"; | |
if (target!=null && (target is Observable || target is List)) { | |
subNotifier = new ObservablePolymerNotifier(_element,target,"${subPath}."); | |
_subNotifiers[name] = subNotifier; | |
} | |
} | |
void close() { | |
_subNotifiers.values.forEach((ObservablePolymerNotifier x) => x.close()); | |
_subNotifiers.clear(); | |
if (_sub!=null) { | |
_sub.cancel(); | |
_sub=null; | |
} | |
} | |
void _notifySplice(List array, String path, int index, int added, List removed) => | |
_element.jsElement.callMethod('_notifySplice', [jsValue(array),path,index,added, jsValue(removed)]); | |
} | |
@behavior | |
abstract class PolymerAutoNotifySupportMixin { | |
ObservablePolymerNotifier _observablePolymerNotifier; | |
static created(mixin) { | |
print("MIXIN CREATED CALLED !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11"); | |
} | |
void attached() { | |
_observablePolymerNotifier = new ObservablePolymerNotifier(this,this); | |
} | |
void detached() { | |
_observablePolymerNotifier.close(); | |
_observablePolymerNotifier=null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I would also use the static
attached
anddetached
methods, instead of the instance methods, otherwise they could be overridden by other mixins.