feat: add observeScrollingInterval in coordinator plugin
This commit is contained in:
parent
7db5d68db5
commit
52e5977d20
@ -18,10 +18,14 @@ package pub.doric.plugin;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.github.pengfeizhou.jscore.JSArray;
|
||||||
import com.github.pengfeizhou.jscore.JSNumber;
|
import com.github.pengfeizhou.jscore.JSNumber;
|
||||||
import com.github.pengfeizhou.jscore.JSObject;
|
import com.github.pengfeizhou.jscore.JSObject;
|
||||||
import com.github.pengfeizhou.jscore.JSValue;
|
import com.github.pengfeizhou.jscore.JSValue;
|
||||||
|
import com.github.pengfeizhou.jscore.JavaValue;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import pub.doric.DoricContext;
|
import pub.doric.DoricContext;
|
||||||
@ -173,4 +177,86 @@ public class CoordinatorPlugin extends DoricJavaPlugin {
|
|||||||
viewNode.blend(jsObject);
|
viewNode.blend(jsObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@DoricMethod(thread = ThreadMode.UI)
|
||||||
|
public void observeScrollingInterval(final JSObject argument, final DoricPromise doricPromise) {
|
||||||
|
getDoricContext().getDriver().asyncCall(new Callable<Object>() {
|
||||||
|
@Override
|
||||||
|
public Object call() throws Exception {
|
||||||
|
JSValue[] scrollableIds = argument.getProperty("scrollable").asArray().toArray();
|
||||||
|
ViewNode<?> scrollNode = null;
|
||||||
|
for (JSValue value : scrollableIds) {
|
||||||
|
if (scrollNode == null) {
|
||||||
|
scrollNode = getDoricContext().targetViewNode(value.asString().value());
|
||||||
|
} else {
|
||||||
|
if (value.isString() && scrollNode instanceof SuperNode) {
|
||||||
|
String viewId = value.asString().value();
|
||||||
|
scrollNode = ((SuperNode<?>) scrollNode).getSubNodeById(viewId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (scrollNode == null) {
|
||||||
|
throw new Exception("Cannot find scrollable view");
|
||||||
|
}
|
||||||
|
String callbackId = argument.getProperty("onScrolledInterval").asString().value();
|
||||||
|
final DoricPromise currentPromise = new DoricPromise(getDoricContext(), callbackId);
|
||||||
|
JSArray observingInterval = argument.getProperty("observingInterval").asArray();
|
||||||
|
final List<Float> interval = new ArrayList<>();
|
||||||
|
for (int i = 0; i < observingInterval.size(); i++) {
|
||||||
|
interval.add(observingInterval.get(i).asNumber().toFloat());
|
||||||
|
}
|
||||||
|
|
||||||
|
JSValue inclusive = argument.getProperty("inclusive");
|
||||||
|
|
||||||
|
final boolean leftInclusive = inclusive.isString() && "Left".equals(inclusive.asString().value());
|
||||||
|
|
||||||
|
final ViewNode<?> finalScrollNode = scrollNode;
|
||||||
|
final int[] rangeIdx = {0};
|
||||||
|
if (finalScrollNode instanceof IDoricScrollable) {
|
||||||
|
((IDoricScrollable) finalScrollNode).addScrollChangeListener(new DoricScrollChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
|
||||||
|
int currentRangeIdx = interval.size();
|
||||||
|
for (int i = 0; i < interval.size(); i++) {
|
||||||
|
if (leftInclusive) {
|
||||||
|
if (scrollY < interval.get(i)) {
|
||||||
|
currentRangeIdx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (scrollY <= interval.get(i)) {
|
||||||
|
currentRangeIdx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rangeIdx[0] != currentRangeIdx) {
|
||||||
|
rangeIdx[0] = currentRangeIdx;
|
||||||
|
currentPromise.resolve(new JavaValue(rangeIdx[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
throw new Exception("Scroller type error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, ThreadMode.UI).setCallback(new AsyncResult.Callback<Object>() {
|
||||||
|
@Override
|
||||||
|
public void onResult(Object result) {
|
||||||
|
doricPromise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable t) {
|
||||||
|
doricPromise.reject();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Group, Panel, List, text, gravity, Color, LayoutSpec, list, listItem, log, vlayout, Gravity, hlayout, Text, refreshable, Refreshable, ListItem, layoutConfig, ViewHolder, ViewModel, VMPanel, loge, modal, stack } from "doric";
|
import { Group, Panel, List, text, gravity, Color, LayoutSpec, list, listItem, log, vlayout, Gravity, hlayout, Text, refreshable, Refreshable, ListItem, layoutConfig, ViewHolder, ViewModel, VMPanel, loge, modal, stack, coordinator } from "doric";
|
||||||
|
|
||||||
interface ItemModel {
|
interface ItemModel {
|
||||||
text: string
|
text: string
|
||||||
@ -64,6 +64,13 @@ class ListVH extends ViewHolder {
|
|||||||
|
|
||||||
class ListVM extends ViewModel<ListModel, ListVH> {
|
class ListVM extends ViewModel<ListModel, ListVH> {
|
||||||
onAttached(state: ListModel, vh: ListVH) {
|
onAttached(state: ListModel, vh: ListVH) {
|
||||||
|
coordinator(this.context).observeScrollingInterval({
|
||||||
|
scrollable: vh.list,
|
||||||
|
observingInterval: [0],
|
||||||
|
onScrolledInterval: (n) => {
|
||||||
|
console.log("onScrolledInterval", n)
|
||||||
|
}
|
||||||
|
});
|
||||||
vh.list.apply({
|
vh.list.apply({
|
||||||
preloadItemCount: 5,
|
preloadItemCount: 5,
|
||||||
canDrag: true,
|
canDrag: true,
|
||||||
|
@ -119,4 +119,57 @@ - (void)setValue:(DoricViewNode *)viewNode isNavBar:(BOOL)isNavBar name:(NSStrin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)observeScrollingInterval:(NSDictionary *)params withPromise:(DoricPromise *)promise {
|
||||||
|
__weak typeof(self) _self = self;
|
||||||
|
[self.doricContext dispatchToMainQueue:^{
|
||||||
|
__strong typeof(_self) self = _self;
|
||||||
|
NSArray <NSString *> *scrollableIds = [params optArray:@"scrollable"];
|
||||||
|
DoricViewNode *scrollNode = nil;
|
||||||
|
for (NSString *value in scrollableIds) {
|
||||||
|
if (!scrollNode) {
|
||||||
|
scrollNode = [self.doricContext targetViewNode:value];
|
||||||
|
} else {
|
||||||
|
if ([scrollNode isKindOfClass:[DoricSuperNode class]]) {
|
||||||
|
scrollNode = [((DoricSuperNode *) scrollNode) subNodeWithViewId:value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!scrollNode) {
|
||||||
|
[promise reject:@"Cannot find scrollable view"];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSString *callbackId = [params optString:@"onScrolledInterval"];
|
||||||
|
NSArray *observingInterval = [params optArray:@"observingInterval"];
|
||||||
|
DoricPromise *currentPromise = [[DoricPromise alloc] initWithContext:self.doricContext
|
||||||
|
callbackId:callbackId];
|
||||||
|
BOOL leftInclusive = [[params optString:@"inclusive"] isEqualToString:@"Left"];
|
||||||
|
if ([scrollNode conformsToProtocol:@protocol(DoricScrollableProtocol)]) {
|
||||||
|
__block NSUInteger rangeIdx = 0;
|
||||||
|
[(id <DoricScrollableProtocol>) scrollNode addDidScrollBlock:^(UIScrollView *scrollView) {
|
||||||
|
CGFloat scrollY = scrollView.contentOffset.y;
|
||||||
|
__block NSUInteger currentRangeIdx = observingInterval.count;
|
||||||
|
[observingInterval enumerateObjectsUsingBlock:^(NSNumber *obj, NSUInteger idx, BOOL *stop) {
|
||||||
|
if (leftInclusive) {
|
||||||
|
if (scrollY < obj.floatValue) {
|
||||||
|
currentRangeIdx = idx;
|
||||||
|
*stop = YES;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (scrollY <= obj.floatValue) {
|
||||||
|
currentRangeIdx = idx;
|
||||||
|
*stop = YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
if (rangeIdx != currentRangeIdx) {
|
||||||
|
rangeIdx = currentRangeIdx;
|
||||||
|
[currentPromise resolve:@(rangeIdx)];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
[promise reject:@"Scroller type error"];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -4597,7 +4597,17 @@ function coordinator(context) {
|
|||||||
context.callNative("coordinator", "verticalScrolling", argument);
|
context.callNative("coordinator", "verticalScrolling", argument);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
observeScrollingInterval: function (argument) {
|
||||||
|
if (context.entity instanceof Panel) {
|
||||||
|
var panel = context.entity;
|
||||||
|
panel.addOnRenderFinishedCallback(function () {
|
||||||
|
argument.scrollable = viewIdChains(argument.scrollable);
|
||||||
|
argument.onScrolledInterval = context.function2Id(argument.onScrolledInterval);
|
||||||
|
context.callNative("coordinator", "observeScrollingInterval", argument);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3563,7 +3563,17 @@ function coordinator(context) {
|
|||||||
context.callNative("coordinator", "verticalScrolling", argument);
|
context.callNative("coordinator", "verticalScrolling", argument);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
observeScrollingInterval: (argument) => {
|
||||||
|
if (context.entity instanceof Panel) {
|
||||||
|
const panel = context.entity;
|
||||||
|
panel.addOnRenderFinishedCallback(() => {
|
||||||
|
argument.scrollable = viewIdChains(argument.scrollable);
|
||||||
|
argument.onScrolledInterval = context.function2Id(argument.onScrolledInterval);
|
||||||
|
context.callNative("coordinator", "observeScrollingInterval", argument);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5103,7 +5103,17 @@ function coordinator(context) {
|
|||||||
context.callNative("coordinator", "verticalScrolling", argument);
|
context.callNative("coordinator", "verticalScrolling", argument);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
observeScrollingInterval: (argument) => {
|
||||||
|
if (context.entity instanceof Panel) {
|
||||||
|
const panel = context.entity;
|
||||||
|
panel.addOnRenderFinishedCallback(() => {
|
||||||
|
argument.scrollable = viewIdChains(argument.scrollable);
|
||||||
|
argument.onScrolledInterval = context.function2Id(argument.onScrolledInterval);
|
||||||
|
context.callNative("coordinator", "observeScrollingInterval", argument);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
6
doric-js/index.d.ts
vendored
6
doric-js/index.d.ts
vendored
@ -1666,6 +1666,12 @@ declare module "doric" {
|
|||||||
end: number | Color;
|
end: number | Color;
|
||||||
};
|
};
|
||||||
}) => void;
|
}) => void;
|
||||||
|
observeScrollingInterval: (argument: {
|
||||||
|
scrollable: Scroller | List | FlowLayout;
|
||||||
|
observingInterval: number[];
|
||||||
|
inclusive?: "Left" | "Right" | undefined;
|
||||||
|
onScrolledInterval: (n: number) => void;
|
||||||
|
}) => void;
|
||||||
};
|
};
|
||||||
export function notch(context: BridgeContext): {
|
export function notch(context: BridgeContext): {
|
||||||
inset: () => Promise<{
|
inset: () => Promise<{
|
||||||
|
6
doric-js/lib/src/native/coordinator.d.ts
vendored
6
doric-js/lib/src/native/coordinator.d.ts
vendored
@ -18,4 +18,10 @@ export declare function coordinator(context: BridgeContext): {
|
|||||||
end: number | Color;
|
end: number | Color;
|
||||||
};
|
};
|
||||||
}) => void;
|
}) => void;
|
||||||
|
observeScrollingInterval: (argument: {
|
||||||
|
scrollable: Scroller | List | FlowLayout;
|
||||||
|
observingInterval: number[];
|
||||||
|
inclusive?: "Left" | "Right" | undefined;
|
||||||
|
onScrolledInterval: (n: number) => void;
|
||||||
|
}) => void;
|
||||||
};
|
};
|
||||||
|
@ -29,6 +29,16 @@ export function coordinator(context) {
|
|||||||
context.callNative("coordinator", "verticalScrolling", argument);
|
context.callNative("coordinator", "verticalScrolling", argument);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
observeScrollingInterval: (argument) => {
|
||||||
|
if (context.entity instanceof Panel) {
|
||||||
|
const panel = context.entity;
|
||||||
|
panel.addOnRenderFinishedCallback(() => {
|
||||||
|
argument.scrollable = viewIdChains(argument.scrollable);
|
||||||
|
argument.onScrolledInterval = context.function2Id(argument.onScrolledInterval);
|
||||||
|
context.callNative("coordinator", "observeScrollingInterval", argument);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -48,21 +48,45 @@ export function coordinator(context: BridgeContext) {
|
|||||||
},
|
},
|
||||||
}) => {
|
}) => {
|
||||||
if (context.entity instanceof Panel) {
|
if (context.entity instanceof Panel) {
|
||||||
const panel = context.entity
|
const panel = context.entity;
|
||||||
panel.addOnRenderFinishedCallback(() => {
|
panel.addOnRenderFinishedCallback(() => {
|
||||||
(argument as any).scrollable = viewIdChains(argument.scrollable)
|
(argument as any).scrollable = viewIdChains(argument.scrollable);
|
||||||
if (argument.target instanceof View) {
|
if (argument.target instanceof View) {
|
||||||
(argument as any).target = viewIdChains(argument.target)
|
(argument as any).target = viewIdChains(argument.target);
|
||||||
}
|
}
|
||||||
if (argument.changing.start instanceof Color) {
|
if (argument.changing.start instanceof Color) {
|
||||||
argument.changing.start = argument.changing.start.toModel()
|
argument.changing.start = argument.changing.start.toModel();
|
||||||
}
|
}
|
||||||
if (argument.changing.end instanceof Color) {
|
if (argument.changing.end instanceof Color) {
|
||||||
argument.changing.end = argument.changing.end.toModel()
|
argument.changing.end = argument.changing.end.toModel();
|
||||||
}
|
}
|
||||||
context.callNative("coordinator", "verticalScrolling", argument)
|
context.callNative("coordinator", "verticalScrolling", argument);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
observeScrollingInterval: (
|
||||||
|
argument: {
|
||||||
|
scrollable: Scroller | List | FlowLayout,
|
||||||
|
// [a_0, a_1, ...a_n] a_n-1<a_n
|
||||||
|
// It represents interval (-∞,a_0),(a_0,a_1), ... (a_n-1,a_n), (a_n, +∞)
|
||||||
|
// the real interval's length is n+1
|
||||||
|
observingInterval: number[],
|
||||||
|
// Left means interval is Left closed right open interval
|
||||||
|
// Right means interval is Left open right closed interval
|
||||||
|
// Default is Right
|
||||||
|
inclusive?: "Left" | "Right",
|
||||||
|
// When scroll accross an,call this function
|
||||||
|
// The argument means that it is scrolled to interval (a_n-1,a_n)
|
||||||
|
onScrolledInterval: (n: number) => void,
|
||||||
|
}) => {
|
||||||
|
if (context.entity instanceof Panel) {
|
||||||
|
const panel = context.entity;
|
||||||
|
panel.addOnRenderFinishedCallback(() => {
|
||||||
|
(argument as any).scrollable = viewIdChains(argument.scrollable);
|
||||||
|
(argument as any).onScrolledInterval = context.function2Id(argument.onScrolledInterval);
|
||||||
|
context.callNative("coordinator", "observeScrollingInterval", argument)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
12
doric-web/dist/index.js
vendored
12
doric-web/dist/index.js
vendored
@ -5178,7 +5178,17 @@ function coordinator(context) {
|
|||||||
context.callNative("coordinator", "verticalScrolling", argument);
|
context.callNative("coordinator", "verticalScrolling", argument);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
observeScrollingInterval: (argument) => {
|
||||||
|
if (context.entity instanceof Panel) {
|
||||||
|
const panel = context.entity;
|
||||||
|
panel.addOnRenderFinishedCallback(() => {
|
||||||
|
argument.scrollable = viewIdChains(argument.scrollable);
|
||||||
|
argument.onScrolledInterval = context.function2Id(argument.onScrolledInterval);
|
||||||
|
context.callNative("coordinator", "observeScrollingInterval", argument);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
doric-web/dist/index.js.map
vendored
2
doric-web/dist/index.js.map
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user